HTTP协议本身是无状态的,即使是同一台电脑同一个浏览器打开同一个页面两次,服务器不知道这两次请求是同一个客户端发送过来的,两次请求是完全独立的。例如,第一次请求时已经登录了,第二次再请求服务器会“忘了”你已经登录过。

为了解决这个问题,就有了Cookie和Session。它们的出现是为了让服务器“记住”之前这个客户端的一些数据,让HTTP保持状态。

下面通过Java Socket实现的HTTP客户端来理解二者之间的原理,以及它们的区别和联系。

HTTP客户端:

Java实现的HTTP客户端有很多种,例如java.net包中的HttpURLConnection,Apache的开源工具HttpComponents。这些都是功能比较完善的HTTP客户端,但是为了看到最底层的HTTP请求和响应,这里用Socket来实现客户端。

下面是Java Socket实现的一个HTTP客户端,为了代码简洁,省略了资源关闭和异常处理:

  1. public static void main(String[] args) throws Exception {
  2. // 地址localhost,端口号8080
  3. Socket socket = new Socket("localhost", 8080);
  4.  
  5. // 请求服务器
  6. OutputStream out = socket.getOutputStream();
  7. PrintWriter pw = new PrintWriter(out);
  8. pw.println("GET /Test/test.jsp HTTP/1.1"); // 请求的第一行Request-Line,需要写请求的URL(/Test/test.jsp)
  9. pw.println("Host: localhost:8080"); // 请求头,Host是必须的
  10. pw.println(); // 一定要有个空行表示请求结束
  11. pw.flush(); // 提交请求
  12.  
  13. // 获取服务器响应
  14. InputStream is = socket.getInputStream();
  15. InputStreamReader reader = new InputStreamReader(is);
  16.  
  17. // 输出响应内容
  18. while (true) {
  19. System.out.print((char)reader.read());
  20. }
  21. }

上面的HTTP客户端通过Socket发送一个最简单的HTTP GET请求到服务器的localhost:8080/Test/test.jsp页面:

GET /Test/test.jsp HTTP/1.1
Host: localhost:8080

然后将服务器的HTTP响应输出。

HTTP服务器:

服务器使用的是Tomcat,页面是上面客户端请求的页面/Test/test.jsp。

Cookie:

修改/Test/test.jsp页面,通过response.addCookie(Cookie cookie)来设置Cookie。

  1. <%
  2. Cookie cookie1 = new Cookie("name", "xxg");
  3. response.addCookie(cookie1); // Cookie在浏览器关闭时失效
  4.  
  5. Cookie cookie2 = new Cookie("age", "22");
  6. cookie2.setMaxAge(60 * 60 * 24 * 7); // 设置Cookie有效期7天
  7. response.addCookie(cookie2);
  8. %>
  9. <html>
  10. <body>
  11. <h1>
  12. Hello
  13. </h1>
  14. </body>
  15. </html>

运行客户端重新,用HTTP客户端来输出服务器发回的响应:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=3B3292C40C9D100E0F2FDC42293225C8; Path=/Test/; HttpOnly
Set-Cookie: name=xxg
Set-Cookie: age=22; Expires=Wed, 18-Dec-2013 05:19:05 GMT
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 72
Date: Wed, 11 Dec 2013 05:19:05 GMT

<html>
  <body>
    <h1>
    Hello
    </h1>
  </body>
</html>

可以看到在响应的Header中有Set-Cookie项,这是服务器将需要设置的Cookie发给客户端,让客户端来保存,当下次再请求时,把Cookie放在请求的Header中发送给服务器。这些在浏览器中都是自动完成。

Session:

Session可以通过session.setAttribute(String name, Object value)来设置,它保存在服务器上,value可以是任何Java类型的对象。当第一次访问jsp时,无论代码中有没有调用session.setAttribute()设置session,都会默认创建Session。

由于HTTP是无状态的,要想知道服务器上某个Session对应的是哪个客户端,就要通过Session ID。

Session ID是由服务器生成,发送给客户端,客户端在以后的请求中带着这个Session ID,就能在服务器中找到对应的Session。

这就类似于第一次去理发店办卡,卡上只有卡号,卡中的余额、消费记录等数据是存在理发店而不是卡中,下次再去的话带着卡,理发店就能查找到对应的记录。

Session ID是如何由服务器发给客户端,再由客户端发给服务器的?一般有两种方式:

一种是URL重写,这种方式不太常用,也不怎么好用,这里也不再详解;

另一种就是最常用的方式Cookie。

在上面输出的HTTP响应中可以找到这样一个Cookie:

Set-Cookie: JSESSIONID=3B3292C40C9D100E0F2FDC42293225C8; Path=/Test/; HttpOnly

这就是服务器发回给客户端的Session ID。由于这个Cookie没有设置Expires有效期,所以在浏览器关闭后就会失效。这也就是Session在浏览器关闭后失效的原因。实际上Session还是保存在服务器上的,并没有真正在服务器上消失,只是对浏览器而言已经重新创建Session并获取Session ID。

修改服务器/Test/test.jsp:

  1. <html>
  2. <body>
  3. <h1>
  4. <%
  5. if(session.getAttribute("user") == null) {
  6. session.setAttribute("user", "xxg");
  7. out.print("null");
  8. }
  9. else {
  10. out.print(session.getAttribute("user"));
  11. }
  12. %>
  13. </h1>
  14. </body>
  15. </html>

当Session中user为空时创建,输出null,不为空时输出放进去的user。

如果用浏览器打开这个页面的话,第一次访问时页面显示null,再刷新一下,就会显示xxg:

但是使用上面Java写的HTTP客户端请求这个页面,无论请求多少次,都会输出null:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=5C196487B8C2FA6742CB7B6E8DC63935; Path=/Test/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 70
Date: Wed, 11 Dec 2013 06:28:41 GMT

<html>
  <body>
    <h1>
    null 
    </h1>
  </body>
</html>

原因就是上面的HTTP客户端并没有把Session ID放在请求中发送给服务器,也就是去理发忘了带卡。

现在复制出上面响应得到的Session ID:

JSESSIONID=5C196487B8C2FA6742CB7B6E8DC63935

在HTTP请求中中加入一个Header,将Seesion ID发回给服务器:

pw.println("Cookie: JSESSIONID=5C196487B8C2FA6742CB7B6E8DC63935");

  1. public static void main(String[] args) throws Exception
  2. {
  3. // 地址localhost,端口号8080
  4. Socket socket = new Socket("localhost", 8080);
  5.  
  6. // 请求服务器
  7. OutputStream out = socket.getOutputStream();
  8. PrintWriter pw = new PrintWriter(out);
  9. pw.println("GET /Test/test.jsp HTTP/1.1"); // 请求的第一行Request-Line,需要写请求的URL(/Test/test.jsp)
  10. pw.println("Host: localhost:8080"); // 请求头,Host是必须的
  11. pw.println("Cookie: JSESSIONID=5C196487B8C2FA6742CB7B6E8DC63935"); // Session ID
  12. pw.println(); // 一定要有个空行表示请求结束
  13. pw.flush(); // 提交请求
  14.  
  15. // 获取服务器响应
  16. InputStream is = socket.getInputStream();
  17. InputStreamReader reader = new InputStreamReader(is);
  18.  
  19. // 输出响应内容
  20. while (true) {
  21. System.out.print((char)reader.read());
  22. }
  23. }

此时请求加入了Session ID的Cookie:

GET /Test/test.jsp HTTP/1.1
Host: localhost:8080
Cookie: JSESSIONID=5C196487B8C2FA6742CB7B6E8DC63935

输出HTTP响应结果:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 69
Date: Wed, 11 Dec 2013 06:32:19 GMT

<html>
  <body>
    <h1>
    xxg 
    </h1>
  </body>
</html>

这样Session才有了效果。

作者:叉叉哥   转载请注明出处:http://blog.csdn.net/xiao__gui/article/details/17298437

Java Socket实现HTTP客户端来理解Session和Cookie的区别和联系的更多相关文章

  1. 深入理解Session和Cookie的区别

    Cookie简介 Cookie意为“甜饼”,是由W3C组织提出,最早由Netscape社区发展的一种机制. 目前Cookie已经成为标准,所有的主流浏览器如IE.Netscape.Firefox.Op ...

  2. 理解Session与Cookie

    写在前面的话:Session和Cookie是非常有意思的两个概念,对于两者的管理可以处理的很复杂,但是无论如何,理解Session和Cookie的基本概念和发明初衷,对于问题的解决,大有裨益. === ...

  3. session与cookie的区别以及HTML5中WebStorage理解

    一.session与cookie的区别 二.HTML5中WebStorage理解 WebStorage的目的是克服由cookie所带来的一些限制,当数据需要被严格控制在客户端时,不需要持续的将数据发回 ...

  4. session与cookie的区别? 如果客户端禁止 cookie session 还能用吗?

    一.session与cookie的区别 session:Session 是存放在服务器端的,类似于Session结构来存放用户数据,当浏览器 第一次发送请求时,服务器自动生成了一个Session和一个 ...

  5. session与cookie的区别,有哪些不同之处

    session与cookie的区别,根据自己的理解总结如下: (1)cookie是一种客户端的状态管理技术,将状态写在 浏览器端,而session是一种服务器端的状态管理技术,将 状态写在web服务器 ...

  6. [转]session和cookie的区别和联系,session的生命周期,多个服务部署时session管理

    Session和Cookie的区别 对象 信息量大小 保存时间 应用范围 保存位置 Session 小量,简单的数据 用户活动时间+一段延迟时间(一般为20分钟) 单个用户 服务器端 Cookie 小 ...

  7. 详解SESSION与COOKIE的区别

    在PHP面试中 经常碰到请阐述session与cookie的区别与联系,以及如何修改两者的有效时间. 大家都知道,session是存储在服务器端的,cookie是存储在客户端的,session依赖于c ...

  8. session与cookie的区别与联系

    session与cookie是在做项目中很常用的会话技术,session与cookie也是面试中被问到频率最高的问题,有一次我去面试,面试官就怼着我session与cookie一直问(头都大了),下面 ...

  9. java Socket通信,客户端与服务端相互发消息

    1.通信过程 网络分为应用层,http.ssh.telnet就是属于这一类,建立在传输层的基础上.其实就是定义了各自的编码解码格式,分层如下: 2.Socket连接 上述通信都要先在传输层有建立连接的 ...

随机推荐

  1. Linux常用解压文件

    tar.gz    tar -zxvf filename.tar.gz tar.bz2  tar -vxjf filename.tar.bz2

  2. [LeetCode]题解(python):027-Remove Element

    题目来源: https://leetcode.com/problems/remove-element/ 题意分析: 给定一个数组和一个数值val,将数组中数值等于val的数去除.不能申请额外空间,超过 ...

  3. iOS显示PDF

    使用UIWebView来显示 //locale file NSString *html = [NSString stringWithContentsOfFile:path1 encoding:NSUT ...

  4. QT无标题窗口在任务栏显示关闭(增加系统菜单)

    在对话框中使用了如下代码: setWindowFlags(Qt::FramelessWindowHint); 在任务栏上右键点击程序,不会弹出菜单,解决办法,使用下面代码: setWindowFlag ...

  5. 【学习】leader特别忙工作到晚上11点左右,组员7点左右下班了,作为leader怎么办?

    Ø  leader先将自己做的事情罗列出来,选出不属于leader当前职责的工作内容. Ø  将不属于leader职责内容的部分授权给组员(承担更多的责任,职责). Ø  授权时,先考察组员的能力和了 ...

  6. 基于visual Studio2013解决C语言竞赛题之0205位数求和

     题目

  7. java学习之IO字符流

    package com.io; import java.io.*; /** * 文件字符流的读取 * @author ganhang * */ public class FileReaderDemo ...

  8. 第二种:NSObject

    - (void)viewDidLoad { [super viewDidLoad]; /** * 开启子线程的方式之一:NSObject */ // 第一个参数:selector // 第二个参数:方 ...

  9. Jenkins Maven打包出错异常的解决方法

    Jenkins是一个很好用的打包部署工具,实现一键式部署项目,在项目处于测试阶段或者对于运维人员来讲是非常方便的一个工具. 但是最近使用Jenkins部署项目时老是出错,主要是maven打包的问题,错 ...

  10. ios inHouse 公布应用

    一.明白几个概念 1.企业版IDP: 即iOS Development Enterprise Program.注意是$299/Year那种.并非$99/Year的那种 2.In House:是指企业内 ...