koorio.com
海量文库 文档专家
当前位置:首页 >> 计算机软件及应用 >>

HTTP与Socket分析与编程

HTTP 与 Socket 分析与编程
一、 TCP/IP 的介绍
首先先介绍一下 TCP/IP,TCP 是传输层协议,IP 是网络层协议。手机能够使用联网 功能是因为手机底层实现了 TCP/IP 协议,可以使手机终端通过无线网络建立 TCP 连 接。TCP 协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络 之上。 建立起一个 TCP 连接需要经过“三次握手”: 第一次握手:客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SEND 状态,等待服务 器确认; 第二次握手:服务器收到 syn 包,必须确认客户的 SYN(ack=j+1) ,同时自己也发送 一个 SYN 包(syn=k) ,即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态; 第三次握手: 客户端收到服务器的 SYN+ACK 包, 向服务器发送确认包 ACK(ack=k+1), 此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。 握手过程中传送的包里不包含数据, 三次握手完毕后, 客户端与服务器才正式开始 传送数据。理想状态下,TCP 连接一旦建立,在通信双方中的任何一方主动关闭 连接 之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断 开 TCP 连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和 客 户端交互,最终确定断开)

二、 HTTP 连接
HTTP 协议即超文本传送协议(Hypertext Transfer Protocol ), Web 联网的基础, 是 也是手机联网常用的协议之一,HTTP 协议是建立在 TCP 协议之上的一种应用,是应 用层协议。 HTTP 连接最显著的特点是客户端发送的每次请求都需要服务器回送响应, 在请求 结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。 1)在 HTTP 1.0 中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请 求后,就自动释放连接。 2)在 HTTP 1.1 中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,

不需要等待一个请求结束后再发送下一个请求。 由于 HTTP 在每次请求结束后都会主动释放连接, 因此 HTTP 连接是一种“短连接”, 要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常 的做法是即 使不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连 接”的请求,服务器在收到该请求后对客户端进行回复,表明知道 客户端“在线”。若服 务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服 务器的回复,则认为网络已经断开。 (一) HTTP 8 种请求方法: 1) 2) 3) 4) 5) 6) 7) 8) GET:请求获取 Request-URI 所标识的资源。 POST:在 Request-URI 所标识的资源后附加新的数据。 HEAD:请求获取 Request-URI 所标识的资源的响应消息头。 OPTIONS:请求查询服务器性能,或查询与资源相关的选项和需求。 PUT:请求服务器存储一个资源,并用 Request-URI 作为其标识。 DELETE:请求服务器删除由 Request-URI 所标识的资源。 TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断。 CONNECT:HTTP1.1 协议中预留给能够将连接改为管道方式的代理服务器。

详解 GET 和 POST 1) GET: GET 方法是默认的 HTTP 请求方法,我们日常用 GET 方法来提交表单数据,然而用 GET 提交的数据只经过简单的编码,同时它将作为 URL 的一部分向 web 服务器发 送,因此使用 GET 方法来提交数据存在着安全隐患,例如: Http://127.0.0.1/login.jsp?Name=zhangshi&Age=30&Submit=%cc%E+%BD%BB 从上面的内容, 可以很容易的辨认出提交表单的内容 (?之后的内容) 另外由 GET , 方法提交的数据是作为 URL 请求的一部分,所以提交的数据量不能太大。 2) POST: POST 方法是 GET 方法的一个替代方法,它主要是向 Web 服务器提交表单数据,尤 其是大批量的数据。 POST 方法克服了 GET 方法的一些缺点。 通过 POST 方法提交表 单数据时, 数据不是作为 URL 请求的一部分而是作为标准数据传送给 Web 服务器, 这就克服了 GET 方法中的信息无法保密和数据量太小的缺点。 因此, 出于安全的考 虑以及对用户隐私的尊重,通常表单提交时采用 POST 方法。

(二) Java 之 HTTP 通信 1. 通过 URLConnection 的通信 通信流程: 第一:创建 URL 以及 HttpURLConnection 对象。 第二:连接参数设置。 第三:连接到服务器。 第四:向服务器写数据。 最后一步:从服务器读取数据。 下面是一些接口的介绍: HttpURLConnection 是 java 的标准类,继承自 URLConnection 类, URLConnection 与 HttpURLConnection 都是抽象类,无法直接实例化对象。其对 象主要通过 URL 的 openConnection 方法获得,创建一个 httpURLConnection 连 接的代码如下所示: URL url = new UR(“http://www.baidu.com”); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); openConnection 方法只创建 URLConnection 或者 HttpURLConnection 实 例,但是并不进行真正的连接操作。并且,每次 openConnection 都将创建一个新 的实例。因此,在连接之前我们可以对其一些属性进行设置,比如超时时间等。 下面对 HttpURLConnetcion 实例的属性设置: //设置输入/输出流 connection.setDoOutput(true); connection.setDoInput(true); //设置请求的方式为 Get 或者 Post connection.setRequestMethod(“GET”); connection.setRequestMethod(“POST”); //在设置 POST 方式时要注意,POST 请求方式不能够使用缓存

connection.setUseCaches(false); 在完成 HttpURLConnection 实例的初始化以后,我们可以分别使用 Get 和 POST 方式来完成一个实例。 下面两个例子是分别使用 GET 和 POST 请求方式的方法例子: 1) GET 请求

package com.dingo.sendurl; import java.net.HttpURLConnection; import java.net.URL; import java.io.IOException; import java.io.InputStream; import java.io.BufferedReader; import java.io.InputStreamReader; public class send_url_get { private String urlStr; private URL url; private HttpURLConnection url_con; private String contentStr;

public void setUrlStr(String urlStr) { this.urlStr = urlStr; } public String getContentStr() { return contentStr; } private void setContentStr(String contentStr) { this.contentStr = contentStr; } public void send_url(){ try{

StringBuilder temp = new StringBuilder(); url = new url(/urlStr); url_con= (HttpURLConnection)url.openConnection(); url_con.setDoOutput(true); url_con.setRequestMethod("GET"); url_con.getOutputStream().flush(); url_con.getOutputStream().close(); InputStream in =url_con.getInputStream(); BufferedReader rd = new BufferedReader(new InputStreamReader(in)); while(rd.read()!=-1){ temp.append(rd.readLine()); } setContentStr(new String (temp)); } catch (Exception e){ e.printStackTrace(); } finally{ if(url_con!=null){ url_con.disconnect(); } } } }

2)

POST 请求

//post package com.dingo.sendurl; import java.net.*; import java.io.InputStream; import java.io.BufferedReader; import java.io.InputStreamReader;

public class send_url_post { private String urlStr; private URL url; private HttpURLConnection url_con; private String response_content;

public void setUrlStr(String urlStr) { this.urlStr = urlStr; } public String getResponse_content() { return response_content; } private void setResponse_content(String response_content) { this.response_content = response_content; } public void send_url(String mobile_number){ try{ url = new url(/urlStr); url_con=(HttpURLConnection)url.openConnection(); url_con.setRequestMethod("POST"); url_con.setDoOutput(true); String param="action=mobile&mobile="+mobile_number;

url_con.getOutputStream().write(param.getBytes()); url_con.getOutputStream().flush(); url_con.getOutputStream().close(); InputStream in= url_con.getInputStream(); BufferedReader rd = new BufferedReader(new InputStreamReader(in)); StringBuilder tempStr=new StringBuilder(); while(rd.read()!=-1){

tempStr.append(rd.readLine()); } setResponse_content(new String(tempStr)); } catch(Exception e){ e.printStackTrace(); } finally{ if(url_con!=null) url_con.disconnect(); } } }

2.

通过 HttpClient 进行通信 HTTP 协议可能是现在 Internet 上使用得最多、 最重要的协议了, 越来越多的 Java 应 用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net 包中已经提供 了访问 HTTP 协议的基本功能, 但是对于大部分应用程序来说, JDK 库本身提供的功能还 不够丰富和灵活。 HttpClient 是 Apache Jakarta Common 下的子项目, 用来提供高效的、 最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新 的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另 外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在 HttpClient 最新版本为 HttpClient 4.2 (GA)。 HttpClient 的主要功能: 1) 2) 3) 4) 实现所有 HTTP 的方法 支持自动转向 支持 HTTPS 协议 支持代理服务器等

使用 HttpClient 的步骤: 1) 2) 创建 HttpClient 实例。 创建某种连接方法的实例,如果是 get 方法就使用 GetMethod,如果是 post 方法,就 使用 PostMethod,然后再方法的构造函数中传入待连接的地址。

3) 4) 5) 6)

调用第一步中创建好的实例的 execute 方法来执行第二部创建好的 method 实例。 读 response 释放连接,无论执行方法是否成功,都要释放连接。 对得到后的内容进行处理。

下面是一些例子用来演示 HttpClient 的使用。 1) 读取网页(http/https)的内容

package http.demo; import java.io.IOException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; /** *最简单的 HTTP 客户端,用来演示通过 GET 或者 POST 方式访问某个页面 *@authorLiudong */ public class SimpleClient { public static void main(String[] args) throws IOException { HttpClient client = new HttpClient(); // 设置代理服务器地址和端口 //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port); // 使用 GET 方法 ,如果服务器需要通过 HTTPS 连接,那只需要将下面 URL 中的 http 换成 https HttpMethod method=new GetMethod("http://java.sun.com"); //使用 POST 方法 //HttpMethod method = new PostMethod("http://java.sun.com"); client.executeMethod(method);

//打印服务器返回的状态 System.out.println(method.getStatusLine()); //打印返回的信息 System.out.println(method.getResponseBodyAsString()); //释放连接 method.releaseConnection(); } }

2)

以 GET 或 POST 方式向网页提交参数 我们知道如果是 GET 的请求方式,那么所有参数都直接放到页面的 URL 后面用问 号与页面地址隔开,每个参数用&隔开,例如: http://java.sun.com/?name=liudong&mobile=123456,但是当使用 POST

方法时就会稍微有一点点麻烦。 本小节的例子演示向如何查询手机号码所在的城市, 代 码如下:
package http.demo; import java.io.IOException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; /** *提交参数演示 *该程序连接到一个用于查询手机号码所属地的页面 *以便查询号码段 1330227 所在的省份以及城市 *@authorLiudong */ public class SimpleHttpClient { public static void main(String[] args) throws IOException { HttpClient client = new HttpClient(); client.getHostConfiguration().setHost( "www.imobile.com.cn" , 80, "http" ); method = getPostMethod(); client.executeMethod(method); // 使用 POST 方式提交数据 //打印服务器返回的状态 //打印结果页面

System.out.println(method.getStatusLine());

Stringresponse=newString(method.getResponseBodyAsString().getBytes("8859_1"));

//打印返回的信息 System.out.println(response); method.releaseConnection(); } /** * 使用 GET 方式提交数据 *@return */ private static HttpMethod getGetMethod(){ return new GetMethod("/simcard.php?simcard=1330227"); } /** * 使用 POST 方式提交数据 *@return */ private static HttpMethod getPostMethod(){ PostMethod post = new PostMethod( "/simcard.php" ); NameValuePair simcard = new NameValuePair( "simcard" , "1330227" ); post.setRequestBody( new NameValuePair[] { simcard}); return post; } }

在上面的例子中页面 http://www.imobile.com.cn/simcard.php 需要一个参数 是 simcard,这个参数值为手机号码段,即手机号码的前七位,服务器会返回提交的手机 号码对应的省份、 城市以及其他详细信息。 GET 的提交方法只需要在 URL 后加入参数信息, 而 POST 则需要通过 NameValuePair 类来设置参数名称和它所对应的值。 3) 处理页面重定向 在 JSP/Servlet 编程中 response.sendRedirect 方法就是使用 HTTP 协议中的 重定向机制。它与 JSP 中的<jsp:forward …>的区别在于后者是在服务器中实现页面的 跳转, 也就是说应用容器加载了所要跳转的页面的内容并返回给客户端; 而前者是返回一个 状态码,这些状态码的可能值见下表,然后客户端读取需要跳转到的页面的 URL 并重新加 载新的页面。就是这样一个过程,所以我们编程的时候就要通过 HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需 要跳转。如果已经确认需要进行页面跳转了,那么可以通过读取 HTTP 头中的 location 属性来获取新的地址。 状态码 301 302 303 307 对应 HttpServletResponse 的常 量 SC_MOVED_PERMANENTLY SC_MOVED_TEMPORARILY SC_SEE_OTHER SC_TEMPORARY_REDIRECT 详细描述 页面已经永久移到另外一个新地址 页面暂时移动到另外一个新的地址 客户端请求的地址必须通过另外 的 URL 来访问 同 SC_MOVED_TEMPORARILY

下面的代码片段演示如何处理页面的重定向
client.executeMethod(post); System.out.println(post.getStatusLine().toString()); post.releaseConnection(); // 检查是否重定向 int statuscode = post.getStatusCode(); if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) || (statuscode == HttpStatus.SC_MO VED_PERMANENTLY) || (statuscode ==HttpStatus.SC_SEE_OTHER) || (statuscode == HttpStatu s.SC_TEMPORARY_REDIRECT)) { // 读取新的 URL 地址 Headerheader=post.getResponseHeader("location"); if (header!=null){ Stringnewuri=header.getValue(); if((newuri==null)||(newuri.equals(""))) newuri="/";

GetMethodredirect=new GetMethod(newuri); client.executeMethod(redirect); System.out.println("Redirect:"+redirect.getStatusLine().toString()); redirect.releaseConnection(); }else System.out.println("Invalid redirect"); }

我们可以自行编写两个 JSP 页面,其中一个页面用 response.sendRedirect 方法 重定向到另外一个页面用来测试上面的例子。

4) 模拟输入用户名和口令进行测试

本小节应该说是 HTTP 客户端编程中最常碰见的问题, 很多网站的内容都只是对注册用 户可见的, 这种情况下就必须要求使用正确的用户名和口令登录成功后, 方可浏览到想要的 页面。因为 HTTP 协议是无状态的,也就是连接的有效期只限于当前请求,请求内容结束后 连接就关闭了。在这种情况下为了保存用户的登录信息必须使用到 Cookie 机制。以 JSP/Servlet 为例,当浏览器请求一个 JSP 或者是 Servlet 的页面时,应用服务器会返 回一个参数,名为 jsessionid(因不同应用服务器而异),值是一个较长的唯一字符串 的 Cookie,这个字符串值也就是当前访问该站点的会话标识。浏览器在每访问该站点的其 他页面时候都要带上 jsessionid 这样的 Cookie 信息,应用服务器根据读取这个会话标 识来获取对应的会话信息。 对于需要用户登录的网站, 一般在用户登录成功后会将用户资料保存在服务器的会话中, 这样当访问到其他的页面时候,应用服务器根据浏览器送上的 Cookie 中读取当前请求对 应的会话标识以获得对应的会话信息, 然后就可以判断用户资料是否存在于会话信息中, 如 果存在则允许访问页面, 否则跳转到登录页面中要求用户输入帐号和口令进行登录。 这就是 一般使用 JSP 开发网站在处理用户登录的比较通用的方法。 这样一来,对于 HTTP 的客户端来讲,如果要访问一个受保护的页面时就必须模拟浏览 器所做的工作,首先就是请求登录页面,然后读取 Cookie 值;再次请求登录页面并加入 登录页所需的每个参数; 最后就是请求最终所需的页面。 当然在除第一次请求外其他的请求 都需要附带上 Cookie 信息以便服务器能判断当前请求是否已经通过验证。说了这么多, 可是如果你使用 httpclient 的话,你甚至连一行代码都无需增加,你只需要先传递登录

信息执行登录过程,然后直接访问想要的页面,跟访问一个普通的页面没有任何区别,因为 类 HttpClient 已经帮你做了所有该做的事情了, 下面的例子实现了这样一个访问的过程。
package http.demo; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.cookie.*; import org.apache.commons.httpclient.methods.*;

/** * 用来演示登录表单的示例 * @author Liudong */ public class FormLoginDemo { static final String LOGON_SITE = "localhost" ; static final int LOGON_PORT = 8080;

public static void main(String[] args) throws Exception{ HttpClient client = new HttpClient(); client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT); // 模拟登录页面 login.jsp->main.jsp PostMethod post = new PostMethod( "/main.jsp" ); NameValuePair name = new NameValuePair( "name" , "ld" ); NameValuePair pass = new NameValuePair( "password" , "ld" ); post.setRequestBody( new NameValuePair[]{name,pass}); int status = client.executeMethod(post); System.out.println(post.getResponseBodyAsString()); post.releaseConnection(); // 查看 cookie 信息 CookieSpec cookiespec = CookiePolicy.getDefaultSpec(); Cookie[] cookies = cookiespec.match(LOGON_SITE, LOGON_PORT, "/" , false , client .getState().getCookies()); if (cookies.length == 0) { System.out.println( "None" ); } else { for ( int i = 0; i < cookies.length; i++) { System.out.println(cookies[i].toString()); } } // 访问所需的页面 main2.jsp GetMethodget=newGetMethod("/main2.jsp"); client.executeMethod(get); System.out.println(get.getResponseBodyAsString()); get.releaseConnection(); } }

5) 提交 XML 格式的参数

提交 XML 格式的参数很简单,仅仅是一个提交时候的 ContentType 问题,下面 的例子演示从文件文件中读取 XML 信息并提交给服务器的过程,该过程可以用来测试 Web 服务。
import java.io.File; import java.io.FileInputStream; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.PostMethod; /** *用来演示提交 XML 格式数据的例子 */ public class PostXMLClient {

public static void main(String[] args) throws Exception { File input = new File(“test.xml”); PostMethod post = new PostMethod(“http://localhost:8080/httpclient/xml.jsp”);

// 设置请求的内容直接从文件中读取 post.setRequestBody( new FileInputStream(input)); if (input.length() < Integer.MAX_VALUE) post.setRequestContentLength(input.length()); else post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);

// 指定请求内容的类型 post.setRequestHeader( "Content-type" , "text/xml; charset=GBK" ); HttpClient httpclient = new HttpClient(); int result = httpclient.executeMethod(post); System.out.println( "Response status code: " + result); System.out.println( "Response body: " ); System.out.println(post.getResponseBodyAsString()); post.releaseConnection(); } }

6) 通过 http 上传文件

httpclient 使用了单独的一个 HttpMethod 子类来处理文件的上传,这个类就是 MultipartPostMethod,该类已经封装了文件上传的细节,我们要做的仅仅是告诉它我 们要上传文件的全路径即可,下面的代码片段演示如何使用这个类。
MultipartPostMethod filePost = new MultipartPostMethod(targetURL); filePost.addParameter( "fileName" , targetFilePath); HttpClient client = new HttpClient(); // 由于要上传的文件可能比较大 , 因此在此设置最大的连接超时时间 client.getHttpConnectionManager(). getParams().setConnectionTimeout(5000); int status = client.executeMethod(filePost);

上面代码中,targetFilePath 即为要上传的文件所在的路径。 7) 访问启用认证的页面

我们经常会碰到这样的页面, 当访问它的时候会弹出一个浏览器的对话框要求输入用户 名和密码后方可,这种用户认证的方式不同于我们在前面介绍的基于表单的用户身份验证。 这是 HTTP 的认证策略, httpclient 支持三种认证方式包括: 基本、 摘要以及 NTLM 认证。 其中基本认证最简单、通用但也最不安全;摘要认证是在 HTTP 1.1 中加入的认证方式, 而 NTLM 则是微软公司定义的而不是通用的规范,最新版本的 NTLM 是比摘要认证还要安 全的一种方式。 下面例子是从 httpclient 的 CVS 服务器中下载的, 它简单演示如何访问一个认证保护的页 面:
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.methods.GetMethod; public class BasicAuthenticationExample { public BasicAuthenticationExample() { } public static void main(String[] args) throws Exception { HttpClient client = new HttpClient(); client.getState().setCredentials( "www.verisign.com" , "realm" , new UsernamePas swordCredentials( "username" , "password" ) ); GetMethod get = new GetMethod( "https://www.verisign.com/products/index.html" ); get.setDoAuthentication( true ); int status = client.executeMethod( get ); System.out.println(status+ "\n" + get.getResponseBodyAsString()); get.releaseConnection();

} }

8) 多线程模式下使用 httpclient 多线程同时访问 httpclient,例如同时从一个站点上下载多个文件。对于同一个 HttpConnection 同一个时间只能有一个线程访问,为了保证多线程工作环境下不产生冲 突,httpclient 使用了一个多线程连接管理器的类: MultiThreadedHttpConnectionManager,要使用这个类很简单,只需要在构造 HttpClient 实例的时候传入即可,代码如下:
MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnection Manager();

HttpClient client = new HttpClient(connectionManager);

以后尽管访问 client 实例即可。

三、 Socket
套接字(socket)是通信的基石,是支持 TCP/IP 协议的网络通信的基本操作 单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息: 连接使用的协议, 本地主机的 IP 地址, 本地进程的协议端口, 远地主机的 IP 地址, 远地进程的协议端口。 应用层通过传输层进行数据通信时,TCP 会遇到同时为多个应用程序进程提 供并发服务的问题。 多个 TCP 连接或多个应用程序进程可能需要通过同一个 TCP 协议端口传输数据。 为了区别不同的应用程序进程和连接, 许多计算机操作系统为 应用程序与 TCP/IP 协议交互提供了套接字(Socket)接口。应 用层可以和传输层 通过 Socket 接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输 的并发服务。 (一) Socket 连接于 TCP 连接的关系 创建 Socket 连接时,可以指定使用的传输层协议,Socket 可以支持不同的传 输层协议(TCP 或 UDP) ,当使用 TCP 协议进行连接时,该 Socket 连接就是一 个 TCP 连接。 (二) Socket 与 HTTP 连接

由于通常情况下 Socket 连接就是 TCP 连接,因此 Socket 连接一旦建立,通 信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用 中, 客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火 墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连 接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。 而 HTTP 连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接, 而且需要客户端向服务器发出请求后,服务器端才能回复数据。 很多情况下, 需要服务器端主动向客户端推送数据, 保持客户端与服务器数据 的实时与同步。此时若双方建立的是 Socket 连接,服务器就可以直接将数据传送 给客户端;若双方建立的是 HTTP 连接,则服务器需要等到客户端发送一次请求 后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可 以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户 端。 (三) Java socket 通信 1. 1V1 通信 服务端:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

package com.dnion.socket;

import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket;

11. public class JabberServer { 12. 13. public static int PORT = 8080; 14. public static void main(String[] agrs) { 15. ServerSocket s = null; 16. Socket socket = null; 17. BufferedReader br = null; 18. PrintWriter pw = null;

19. try { 20. //设定服务端的端口号 21. s = new ServerSocket(PORT); 22. System.out.println("ServerSocket Start:"+s); 23. //等待请求,此方法会一直阻塞,直到获得请求才往下走 24. socket = s.accept(); 25. System.out.println("Connection accept socket:"+socket); 26. //用于接收客户端发来的请求 27. br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 28. //用于发送返回信息,可以不需要装饰这么多 io 流使用缓冲流时发送数据要注意调用.flush()方法 29. pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true); 30. while(true){ 31. String str = br.readLine(); 32. if(str.equals("END")){ 33. break; 34. } 35. System.out.println("Client Socket Message:"+str); 36. Thread.sleep(1000); 37. pw.println("Message Received"); 38. pw.flush(); 39. } 40. 41. } catch (Exception e) { 42. // TODO Auto-generated catch block 43. e.printStackTrace(); 44. }finally{ 45. System.out.println("Close....."); 46. try { 47. br.close(); 48. pw.close(); 49. socket.close(); 50. s.close(); 51. } catch (Exception e2) { 52. 53. } 54. } 55. } 56. }

客户端:

1. package com.dnion.socket; 2. 3. import java.io.BufferedReader; 4. import java.io.BufferedWriter; 5. import java.io.IOException; 6. import java.io.InputStreamReader; 7. import java.io.OutputStreamWriter; 8. import java.io.PrintWriter; 9. import java.net.Socket; 10. 11. public class JabberClient { 12. 13. public static void main(String[] args) { 14. Socket socket = null; 15. BufferedReader br = null; 16. PrintWriter pw = null; 17. try { 18. //客户端 socket 指定服务器的地址和端口号 19. socket = new Socket("127.0.0.1", JabberServer.PORT); 20. System.out.println("Socket=" + socket); 21. //同服务器原理一样 22. br = new BufferedReader(new InputStreamReader( 23. socket.getInputStream())); 24. pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter( 25. socket.getOutputStream()))); 26. for (int i = 0; i < 10; i++) { 27. pw.println("howdy " + i); 28. pw.flush(); 29. String str = br.readLine(); 30. System.out.println(str); 31. } 32. pw.println("END"); 33. pw.flush(); 34. } catch (Exception e) { 35. e.printStackTrace(); 36. } finally { 37. try { 38. System.out.println("close......"); 39. br.close(); 40. pw.close(); 41. socket.close();

42. } catch (IOException e) { 43. // TODO Auto-generated catch block 44. e.printStackTrace(); 45. } 46. } 47. } 48. 49. }

2.

一对多通信,使用多线程实现 服务端: 服务类:

1. 2. 3. 4. 5. 6. 7. 8. 9.

package com.dnion.socket;

import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;

public class MultiJabberServer {

10. public static void main(String[] args) { 11. ServerSocket s = null; 12. Socket socket = null; 13. try { 14. s = new ServerSocket(8080); 15. //等待新请求、否则一直阻塞 16. while(true){ 17. socket = s.accept(); 18. System.out.println("socket:"+socket); 19. new ServeOneJabbr(socket); 20. 21. } 22. } catch (Exception e) { 23. try { 24. socket.close(); 25. } catch (IOException e1) {

26. // TODO Auto-generated catch block 27. e1.printStackTrace(); 28. } 29. }finally{ 30. try { 31. s.close(); 32. } catch (IOException e) { 33. // TODO Auto-generated catch block 34. e.printStackTrace(); 35. } 36. } 37. 38. 39. } 40. 41. }

服务端响应请求的类:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

package com.dnion.socket;

import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket;

11. public class ServeOneJabbr extends Thread{ 12. 13. private Socket socket = null; 14. private BufferedReader br = null; 15. private PrintWriter pw = null; 16. 17. public ServeOneJabbr(Socket s){ 18. socket = s; 19. try { 20. br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 21. pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);

22. start(); 23. } catch (Exception e) { 24. 25. e.printStackTrace(); 26. } 27. } 28. 29. @Override 30. public void run() { 31. while(true){ 32. String str; 33. try { 34. str = br.readLine(); 35. if(str.equals("END")){ 36. br.close(); 37. pw.close(); 38. socket.close(); 39. break; 40. } 41. System.out.println("Client Socket Message:"+str); 42. pw.println("Message Received"); 43. pw.flush(); 44. } catch (Exception e) { 45. try { 46. br.close(); 47. pw.close(); 48. socket.close(); 49. } catch (IOException e1) { 50. // TODO Auto-generated catch block 51. e1.printStackTrace(); 52. } 53. } 54. } 55. } 56. 57. 58. 59. }

客户端同 1V1 的客户端一样。

四、


推荐相关:

Socket与Http网络编程.doc

Socket与Http网络编程 - 1.Sockt 网络编程 1.网络编程三要素


通过一个SOCKET例子理解HTTP协议.pdf

通过一个 Socket 例子理解 Http 协议 来自:http://tech.163.com/tm/030531/...一些介绍 Internet 编程的书籍把这个 CRLF 视为 HTTP 请求的第四个组成部分。 ...


Http和Socket.doc

Http和Socket - android 手机开发 http与socket区别... Http和Socket_IT/计算机_专业资料。android 手机开发 ...HTTP与Socket分析与编程 22页 免费 有关Socket与HTTP...


SOCKET与TCPIP与HTTP的关系.txt

SOCKET与TCP/IP与HTTP的关系 4.1 SOCKET 与TCP/IP 关系 Socket 是一种应用...HTTP与Socket分析与编程 22页 免费 2018 Baidu |由 百度云 提供计算服务 ...


有关Socket与HTTP的基础知识(一).doc

有关Socket与HTTP的基础知识(一) - 有关 SocketHTTP 的基础知识 MOMO 就不赘述拉,不懂得朋友自己谷歌吧。我们项 目的需求是在登录的时候使用 HTTP 请求,...


通过一个Socket例子理解Http协议.doc

用 Java 构造 Web 服务器主要用二个类,java.net.Socket java.net.Server...一些介绍 Internet 编程的书籍把这个 CRLF 视为 HTTP 请求的第四个组成部分。 ...


TCPIPHttpSocket的区别.txt

传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的,而Socket本身不算是协议,就像上面所说,它只是提供了一个针对TCP或者UDP编程的...


基于Socket的网络编程技术及其实现.doc

基于Socket的网络编程技术及其实现 - 龙源期刊网 http://www.qikan.com.cn 基于 Socket 的网络编程技术及其实现 作者:许文勇 来源:《无线互联科技》2014...


TCPIP、Http、Socket的区别.doc

IP 协议的,而应用层的 HTTP 协议又 是基于传输层的 TCP 协议的,而 Socket 本身不算是协议,就像上面所说,它只 是提供了一个针对 TCP 或者 UDP 编程的接口。...


http、TCPIP协议与socket之间的区别.doc

http、TCPIP协议与socket之间的区别 - http、TCP/IP 协议与 socket 之间的区别 1、TCP/IP 连接 手机能够使用联网功能是因为手机底层实现了 TCP/IP 协...


基于SOCKET编程接口的网络通信.doc

基于SOCKET编程接口的网络通信 - 龙源期刊网 http://www.qikan.com.cn 基于 SOCKET 编程接口的网络通信 作者:宋泽瑞 来源:《中国新通信》2017 年第 0...


Http和Socket连接区别.doc

HTTP与Socket分析与编程 22页 1财富值喜欢此文档的还喜欢 HTTP协


用Socket类实现HTTP协议客户端应用.doc

Socket类实现HTTP协议客户端应用用Socket类实现HTTP协议客户端应用隐藏>> 用Socket 类实现 HTTP 协议客户端应用 Http 客户端程序已集成在 Java 语言中,可以通过 ...


基于socket的http的请求监听程序的设计本科学位论文_图文.doc

基于sockethttp的请求监听程序的设计本科学位论文_...掌握高级语言及网络编程知识,可以选 择 Visual C++...起止日期 7.9 工作内容 分析课题,寻找相关资料。 ...


多线程和Socket网络编程_图文.ppt

Demo4:执行带参数的方法 高级软件人才实作培训专家 SOCKET 网络编程 高级...我杨浩然打电话 电话 规定好的语 言 电脑电脑进行联系 Socket HTTP协 议 ...


实验5 socket网络编程_图文.doc

实验5 socket网络编程_计算机软件及应用_IT/计算机_...使用 URL 类下载深圳大学首页 http://www.szu.edu...并给出个人对结果的分析、结论) 实验过程与截图即...


TCP和UDP和socket网络编程_图文.ppt

TCP和UDP和socket网络编程 - 网络编程 主讲人:孙鑫 http://


Socket编程指南及示例程序 VC.doc

Socket编程指南示例程序 VC - 转自一位大虾的 BLOG,代码的压缩包位置是 http://www.blogjava.net/Files/wxb_nudt/socket_src.rar...


Socket网络通信概述解析_图文.ppt

广州大学华软软件学院 网络技术系 Socket网络通信 概述 ---Socket编程实践王婵娟...浏览网页HTTP服务80端口、FTP服务21端口等。见书P8… 7 IPAddress类 ? 在...


网络socket编程汇总.doc

网络socket编程汇总 - [精华] 网络 socket 编程指南 精华] http://www.chinaunix.net 作者:流浪者 发表于:2008-04-20 15:21:55 B...

网站首页 | 网站地图
All rights reserved Powered by 酷我资料网 koorio.com
copyright ©right 2014-2019。
文档资料库内容来自网络,如有侵犯请联系客服。zhit325@126.com