收藏 分销(赏)

java技巧-传输协议.doc

上传人:s4****5z 文档编号:8822804 上传时间:2025-03-03 格式:DOC 页数:41 大小:1.47MB
下载 相关 举报
java技巧-传输协议.doc_第1页
第1页 / 共41页
java技巧-传输协议.doc_第2页
第2页 / 共41页
点击查看更多>>
资源描述
传输协议 TCP/IP 三次握手,建立连接 四次挥手,断开连接 层次结构 TCP/IP OSI 应用层 应用层 表示层 会话层 主机到主机层(TCP)(又称传输层) 传输层 网络层(IP)(又称互联层) 网络层 网络接口层(又称链路层) 数据链路层 物理层 TCP三次握手 所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。 三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。 · 第一次握手: 客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。 · 第二次握手: 服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即X+1。 · 第三次握手. 客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1 SYN攻击 在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态. Syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。 Syn攻击是一个典型的DDOS攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击 netstat -n -p TCP | grep SYN_RECV 一般较新的TCP/IP协议栈都对这一过程进行修正来防范Syn攻击,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等. 但是不能完全防范syn攻击。 TCP 四次挥手 TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。 参见wireshark抓包,实测的抓包结果并没有严格按挥手时序。我估计是时间间隔太短造成。 UDP TCP/IP与UDP区别 TCP/IP协议时面向连接,UDP面向非连接 TCP/IP编程 ServerSocket,Socket Http详解 HTTP协议详解之请求篇 http请求由三部分组成,分别是:请求行、消息报头、请求正文 1、请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Method Request-URI HTTP-Version CRLF 其中 Method表示请求方法;Request-URI是一个统一资源标识符;HTTP-Version表示请求的HTTP协议版本;CRLF表示回车和换行(除了作为结尾的CRLF外,不允许出现单独的CR或LF字符)。 请求方法(所有方法全为大写)有多种,各个方法的解释如下: GET 请求获取Request-URI所标识的资源 POST 在Request-URI所标识的资源后附加新的数据 HEAD 请求获取由Request-URI所标识的资源的响应消息报头 PUT 请求服务器存储一个资源,并用Request-URI作为其标识 DELETE 请求服务器删除Request-URI所标识的资源 TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断 CONNECT 保留将来使用 OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求 应用举例: GET方法:在浏览器的地址栏中输入网址的方式访问网页时,浏览器采用GET方法向服务器获取资源,eg:GET /form.html HTTP/1.1 (CRLF) POST方法要求被请求服务器接受附在请求后面的数据,常用于提交表单。 eg:POST /reg.jsp HTTP/ (CRLF) Accept:image/gif,image/x-xbit,... (CRLF) ... HOST: (CRLF) Content-Length:22 (CRLF) Connection:Keep-Alive (CRLF) Cache-Control:no-cache (CRLF) (CRLF) //该CRLF表示消息报头已经结束,在此之前为消息报头 user=jeffrey&pwd=1234 //此行以下为提交的数据 HEAD方法与GET方法几乎是一样的,对于HEAD请求的回应部分来 说,它的HTTP头部中包含的信息与通过GET请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到Request-URI所标识 的资源的信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新。 2、请求报头后述 3、请求正文(略) HTTP详解之响应篇 在接收和解释请求消息后,服务器返回一个HTTP响应消息。 HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文 1、状态行格式如下: HTTP-Version Status-Code Reason-Phrase CRLF 其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。 状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值: 1xx:指示信息--表示请求已接收,继续处理 2xx:成功--表示请求已被成功接收、理解、接受 3xx:重定向--要完成请求必须进行更进一步的操作 4xx:客户端错误--请求有语法错误或请求无法实现 5xx:服务器端错误--服务器未能实现合法的请求 常见状态代码、状态描述、说明: 200 OK //客户端请求成功 400 Bad Request //客户端请求有语法错误,不能被服务器所理解 401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 403 Forbidden //服务器收到请求,但是拒绝提供服务 404 Not Found //请求资源不存在,eg:输入了错误的URL 500 Internal Server Error //服务器发生不可预期的错误 503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常 eg:HTTP/1.1 200 OK (CRLF) 2、响应报头后述 3、响应正文就是服务器返回的资源的内容 HTTP详解之消息报头篇 HTTP消息由客户端到服务器的请求和服务器到客户端的响应组成。请求消息和响应消息都是由开始行(对于请求消息,开始行就是请求行,对于响应消息,开始行就是状态行),消息报头(可选),空行(只有CRLF的行),消息正文(可选)组成。 HTTP消息报头包括普通报头、请求报头、响应报头、实体报头。 每一个报头域都是由名字+“:”+空格+值 组成,消息报头域的名字是大小写无关的。 1、普通报头 在普通报头中,有少数报头域用于所有的请求和响应消息,但并不用于被传输的实体,只用于传输的消息。 eg: Cache-Control 用于指定缓存指令,缓存指令是单向的(响应中出现的缓存指令在请求中未必会出现),且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制),HTTP1.0使用的类似的报头域为Pragma。 请求时的缓存指令包括:no-cache(用于指示请求或响应消息不能缓存)、no-store、max-age、max-stale、min-fresh、only-if-cached; 响应时的缓存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage. eg:为了指示IE浏览器(客户端)不要缓存页面,服务器端的JSP程序可以编写如下:response.sehHeader("Cache-Control","no-cache"); //response.setHeader("Pragma","no-cache");作用相当于上述代码,通常两者//合用 这句代码将在发送的响应消息中设置普通报头域:Cache-Control:no-cache Date普通报头域表示消息产生的日期和时间 Connection普通报头域允许发送指定连接的选项。例如指定连接是连续,或者指定“close”选项,通知服务器,在响应完成后,关闭连接 2、请求报头 请求报头举例: GET /form.html HTTP/1.1 (CRLF) Accept:image/gif,image/x-xbitmap,image/jpeg,application/x-shockwave-flash,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/* (CRLF) Accept-Language:zh-cn (CRLF) Accept-Encoding:gzip,deflate (CRLF) If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF) If-None-Match:W/"80b1a4c018f3c41:8317" (CRLF) User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF) Host: (CRLF) Connection:Keep-Alive (CRLF) (CRLF) 3、响应报头 响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。 常用的响应报头 Location Location响应报头域用于重定向接受者到一个新的位置。Location响应报头域常用在更换域名的时候。 Server Server响应报头域包含了服务器用来处理请求的软件信息。与User-Agent请求报头域是相对应的。下面是 Server响应报头域的一个例子: Server:Apache-Coyote/1.1 4、实体报头 请求和响应消息都可以传送一个实体。一个实体由实体报头域和实体正文组成,但并不是说实体报头域和实体正文要在一起发送,可以只发送实体报头域。实体报头定义了关于实体正文(eg:有无实体正文)和请求所标识的资源的元信息。 常用的实体报头 Content-Encoding Content-Encoding实体报头域被用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容的编码,因而要获得Content- Type报头域中所引用的媒体类型,必须采用相应的解码机制。Content-Encoding这样用于记录文档的压缩方法,eg:Content- Encoding:gzip Content-Language Content-Language实体报头域描述了资源所用的自然语言。没有设置该域则认为实体内容将提供给所有的语言阅读 者。eg:Content-Language:da Content-Length Content-Length实体报头域用于指明实体正文的长度,以字节方式存储的十进制数字来表示。 Content-Type Content-Type实体报头域用语指明发送给接收者的实体正文的媒体类型。eg: Content-Type:text/html;charset=ISO-8859-1 Content-Type:text/html;charset=GB2312 Last-Modified Last-Modified实体报头域用于指示资源的最后修改日期和时间。 Expires Expires实体报头域给出响应过期的日期和时间。为了让代理服务器或浏览器在一段时间以后更新缓存中(再次访问曾访问过的页面时,直接从缓存中加载, 缩短响应时间和降低服务器负载)的页面,我们可以使用Expires实体报头域指定页面过期的时间。eg:Expires:Thu,15 Sep 2006 16:23:12 GMT HTTP1.1的客户端和缓存必须将其他非法的日期格式(包括0)看作已经过期。eg:为了让浏览器不要缓存页面,我们也可以利用Expires实体报头域,设置为0,jsp中程序如下:response.setDateHeader("Expires","0"); 利用telnet观察http协议的通讯过程 实验目的及原理: 利用MS的telnet工具,通过手动输入http请求信息的方式,向服务器发出请求,服务器接收、解释和接受请求后,会返回一个响应,该响应会在telnet窗口上显示出来,从而从感性上加深对http协议的通讯过程的认识。 实验步骤: 1、打开telnet 1.1 打开telnet 运行-->cmd-->telnet 1.2 打开telnet回显功能 set localecho 2、连接服务器并发送请求 2.1 open 80 //注意端口号不能省略 HEAD /index.asp HTTP/1.0 Host: /*我们可以变换请求方法,请求桂林电子主页内容,输入消息如下*/ open 80 GET /index.asp HTTP/1.0 //请求资源的内容 Host: 2.2 open 80 //在命令提示符号下直接输入telnet 80 HEAD /index.asp HTTP/1.0 Host: 3 实验结果: 3.1 请求信息2.1得到的响应是: HTTP/1.1 200 OK //请求成功 Server: Microsoft-IIS/5.0 //web服务器 Date: Thu,08 Mar 200707:17:51 GMT Connection: Keep-Alive Content-Length: 23330 Content-Type: text/html Expries: Thu,08 Mar 2007 07:16:51 GMT Set-Cookie: ASPSESSIONIDQAQBQQQB=BEJCDGKADEDJKLKKAJEOIMMH; path=/ Cache-control: private //资源内容省略 3.2 请求信息2.2得到的响应是: HTTP/1.0 404 Not Found //请求失败 Date: Thu, 08 Mar 2007 07:50:50 GMT Server: Apache/2.0.54 <Unix> Last-Modified: Thu, 30 Nov 2006 11:35:41 GMT ETag: "6277a-415-e7c76980" Accept-Ranges: bytes X-Powered-By: mod_xlayout_jh/0.0.1vhs.markII.remix Vary: Accept-Encoding Content-Type: text/html X-Cache: MISS from zjm152- Via: 1.0 zjm152-:80<squid/2.6.STABLES-20061207> X-Cache: MISS from th- Connection: close HttpClient 核心类描述 * <pre> * 主要类: * 客户端 * HttpClient, * 请求(post|get) * HttpPost(HttpGet), * 请求数据 * HttpEntity * 简单的表单数据 * UrlEncodedFormEntity <----List<NameValuePair> * 带文件的数据 * MultipartEntity增加FileBody,StringBody * 请求设置请求数据 * HttpPost(HttpGet).setEntity(HttpEntity entity); * 客户端执行请求 * HttpResponse resp = HttpClient.execute(HttpPost|HttpGet) * 响应 * HttpResponse * 响应数据 * HttpResponse.getEntity(); * 中文乱码 * 请求数据的编码: * UrlEncodedFormEntity reqEntity = new UrlEncodedFormEntity * (formparams,"UTF-8"); * Charset utf8 = Charset.forName("UTF-8"); * StringBody sb = new StringBody("简单表单数据值1", utf8); * 响应数据的编码: * String respString = EntityUtils.toString(resEntity, "UTF-8"); * 使用连接池 * 编写连接池类 * HttpClientPool, * 客户端使用的时候代码: * HttpClient httpclient = HttpClientPool. * getInstance().getHttpClient(); * 保持会话 * 比如tomcat的session使用cookie实现 * 首先,客户端项服务器发送登录请求, * 登录成功,服务端向客户端写一个cookie,里面存放jsessionid * 以后,客户端每次请求服务端的时候, * 在请求的消息头中将jsessionid放在cookie中带过去, * //定义存放sessionid的threadlocal * private ThreadLocal<String> jsessionid=new ThreadLocal<String>(); * //登录,得到响应的头信息中的cookie(jsessionid) * Header h = response.getFirstHeader("Set-Cookie"); * if(h!=null){ * System.out.println("h-->"+h.getName()+":"+h.getValue()); * String cookie = h.getValue(); * //放在threadlocal中,供后面的逻辑代码使用 * jsessionid.set(cookie.substring(0,cookie.indexOf(";"))); * } * //登录以后, * String cookie = jsessionid.get(); //拿到threadlocal中的cookie值 * httppost.setHeader("cookie", cookie);//设置请求头中的cookie * * </pre> 版本 3.x和4.x有很大区别 4.1需要的jar包 httpclient-4.1.jar httpclient-cache-4.1.jar httpcore-4.1.jar httpmime-4.1.jar (上传文件需要) 发送请求 // 测试发送请求 @Test public void login() { String url = "http://localhost:8080" + "/course-ssh2-anno-demo" + "/httpClient/login.action"; // 得到客户端HttpClient HttpClient httpclient = new DefaultHttpClient(); // 得到请求HttpPost HttpPost httppost = new HttpPost(url); try { // 定义表单数据 List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("username", "aaa")); formparams.add(new BasicNameValuePair("password", "aaa")); // 定义请求数据 UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity( formparams, "UTF-8"); // 请求设置请求数据 httppost.setEntity(uefEntity); System.out.println("executing request " + httppost.getURI()); // 客户端执行请求,得到响应HttpResponse HttpResponse response = httpclient.execute(httppost); // 得到响应的消息体(响应数据) HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println("--------------------------------------"); System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8")); System.out.println("--------------------------------------"); } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭连接,释放资源 httpclient.getConnectionManager().shutdown(); } } 发送附件 // 测试上传文件 @Test public void uploadFile() { HttpClient httpclient = null; try { //定义客户端 httpclient = new DefaultHttpClient(); //定义请求 HttpPost httppost = new HttpPost("http://localhost:8080" + "/course-ssh2-anno-demo" + "/httpClient/uploadFile.action"); //定义Multipart类型的消息体(请求数据) MultipartEntity reqEntity = new MultipartEntity(); String path = getExcelPath("member.xlsx"); //定义文件数据 FileBody bin = new FileBody(new File(path)); //Multipart类型的消息体添加文件数据 reqEntity.addPart("upload", bin);// upload为请求后台的File upload属性 //Multipart类型的消息体添加普通表单域数据 // 设置传输的参数编码为UTF-8,解决中文乱码问题 Charset utf8 = Charset.forName("UTF-8"); reqEntity.addPart("param1", new StringBody("简单表单数据值1", utf8)); reqEntity.addPart("param2", new StringBody("简单表单数据值2", utf8)); //请求设置消息体(请求数据) httppost.setEntity(reqEntity); //客户端执行请求,得到响应 HttpResponse response = httpclient.execute(httppost); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == org.apache.http.HttpStatus.SC_OK) { HttpEntity resEntity = response.getEntity(); // httpclient自带的工具类读取返回数据 // 设置编码为UTF-8,解决中文乱码问题 String respString = EntityUtils.toString(resEntity, "UTF-8"); System.out.println(respString); EntityUtils.consume(resEntity); } } catch (Exception e) { e.printStackTrace(); } finally { try { httpclient.getConnectionManager().shutdown();//释放连接 } catch (Exception ignore) { } } } httpclient连接池 定义连接池 public class HttpClientPool { private HttpParams httpParams; private ClientConnectionManager connectionManager; private static HttpClientPool inst = new HttpClientPool(); /** * 最大连接数 */ public final static int MAX_TOTAL_CONNECTIONS = 100; /** * 获取连接的最大等待时间 */ public final static int WAIT_TIMEOUT = 60 * 1000; /** * 每个路由最大连接数 */ public final static int MAX_ROUTE_CONNECTIONS = MAX_TOTAL_CONNECTIONS/2; /** * 连接超时时间 */ public final static int CONNECT_TIMEOUT = 30 * 1000; /** * 读取超时时间 */ public final static int READ_TIMEOUT = 30 * 1000; public static HttpClientPool getInstance() { return inst; } private HttpClientPool() { this.httpParams = new BasicHttpParams(); // 设置最大连接数 ConnManagerParams.setMaxTotalConnections(httpParams, MAX_TOTAL_CONNECTIONS); // 设置获取连接的最大等待时间 ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT); // 设置每个路由最大连接数 ConnPerRouteBean connPerRoute = new ConnPerRouteBean( MAX_ROUTE_CONNECTIONS); ConnManagerParams.setMaxConnectionsPerRoute(httpParams, connPerRoute); // 设置连接超时时间 HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT); // 设置读取超时时间 HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory .getSocketFactory(), 8080)); // registry.register(new Scheme("http", PlainSocketFactory // .getSocketFactory(), 8080)); registry.register(new Scheme("https", SSLSocketFactory .getSocketFactory(), 443)); this.connectionManager = new ThreadSafeClientConnManager(httpParams, registry); } /** * 从连接池得到连接 * @return */ public HttpClient getHttpClient() { return new DefaultHttpClient(this.connectionManager, this.httpParams); } private HttpClientPool(HttpParams httpParams, ClientConnectionManager connectionManager) { super(); this.httpParams = httpParams; this.connectionManager = connectionManager; } } 使用连接池 HttpClient httpclient = HttpClientPool.getInstance().getHttpClient(); 模拟浏览器模式 httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); 保持会话 @Test public void keepSession() { // 首先登录 String url = "http://localhost:8080" + "/course-ssh2-anno-demo" + "/httpClient/login.action"; String cookieJsessionId = sendLoginRequest(url); // 然后访问(需要登录之后才能访问的)资源 sendRequestAfterLogin(cookieJsessionId); } // 发送登录的请求 private String sendLoginRequest(String url) { String cookieJsessionId = null; HttpClient httpclient = HttpClientPool.getInstance().getHttpClient(); HttpPost httppost = new HttpPost(url); List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("username", "aaa")); formparams.add(new BasicNameValuePai
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 通信科技 > 网络/通信

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服