`

Java Socket现实简单的HTTP服务

    博客分类:
  • Java
阅读更多

一个简单的用 Java Socket 编写的 HTTP 服务器应用, 演示了请求和应答的协议通信内容以及给客户端返回 HTML 文本和二进制数据文件(一个图片), 同时展示了 404, 200 等状态码.

  
首先运行这个程序,然后打开Web浏览器,键入http://localhost,则这个程序能够显示出浏览器发送了那些信息并且向浏览器返回一个网页和一副图片, 并测试同浏览器对话.  当浏览器看到 HTML 中带有图片地址时, 则会发出第二次连接来请求图片等资源.  这个例子可以帮您理解 Java 的 HTTP 服务器软件是基于 J2SE 的 Socket 等软件编写的概念, 并熟悉HTTP 协议.  相反的用 Telnet 连接到已有的服务器则可以帮忙理解浏览器的运行过程和服务器端的返回内容.  
   
当用户在Web浏览器地址栏中输入一个带有http://前缀的URL并按下Enter后,或者在Web页面中某个以http://开头的超链接上单击鼠标,HTTP事务处理的第一个阶段--建立连接阶段就开始了.HTTP的默认端口是80.  随着连接的建立,HTTP就进入了客户向服务器发送请求的阶段.客户向服务器发送的请求是一个有特定格式的ASCII消息,其语法规则为: 


  < Method > < URL > < HTTP Version > <\r\n> 
  { <Header>:<Value> <\r\n>} 
  <\r\n> 
  { Entity Body } 


请求消息的顶端是请求行,用于指定方法,URL和HTTP协议的版本,请求行的最后是回车换行.方法GET,POST,HEAD,PUT,DELETE等.  在请求行之后是若干个报头(Header)行.每个报头行都是由一个报头和一个取值构成的二元对,报头和取值之间以":"分隔;报头行的最后是回车换行.常见的报头有Accept(指定MIME媒体类型),Accept_Charset(响应消息的编码方式),Accept_Encoding(响应消息的字符集),User_Agent(用户的浏览器信息)等.  在请求消息的报头行之后是一个回车换行,表明请求消息的报头部分结束.在这个之后是请求消息的消息实体(Entity Body).具体的例子参看httpRequest.txt. 

Web服务器在收到客户请求并作出处理之后,要向客户发送应答消息.与请求消息一样,应答消息的语法规则为: 


  < HTTP Version> <Status Code> [<Message>]<\r\n> 
  { <Header>:<Value> <\r\n> }  
  <\r\n> 
  { Entity Body } 


应答消息的第一行为状态行,其中包括了HTTP版本号,状态码和对状态码进行简短解释的消息;状态行的最后是回车换行.状态码由3位数字组成,有5类:  


  参看:HTTP应答码及其意义  
   
  1XX 保留  
  2XX 表示成功  
  3XX 表示URL已经被移走  
  4XX 表示客户错误  
  5XX 表示服务器错误  


例如:415,表示不支持改媒体类型;503,表示服务器不能访问.最常见的是200,表示成功.常见的报头有:Last_Modified(最后修改时间),Content_Type(消息内容的MIME类型),Content_Length(内容长度)等. 

在报头行之后也是一个回车换行,用以表示应答消息的报头部分的结束,以及应答消息实体的开始. 

下面是一个应答消息的例子: 
  HTTP/1.0 200 OK 
  Date: Moday,07-Apr-97 21:13:02 GMT 
  Server:NCSA/1.1 
  MIME_Version:1.0 
  Content_Type:text/html 
  Last_Modified:Thu Dec 5 09:28:01 1996 
  Coentent_Length:3107 
   
  <HTML><HEAD><TITLE></HTML>  
   
在用Java语言实现HTTP服务器时,首先启动一个java.net.ServerSocket在提供服务的端口上监听连接.向客户返回文本时,可以用 PrintWriter,但是如果返回二进制数据,则必须使用OutputStream.write(byte[])方法,返回的应答消息字符串可以使用 String.getBytes()方法转换为字节数组返回,或者使用PrintStream的print()方法写入文本,用 write(byte[])方法写入二进制数据. 

 

源程序来自http://blog.csdn.net/myeclipse_java,本程序是在原有基础上进行了一些调整,源程序在POST请求时会阻塞,本程序解决了此问题,另外,本程序在原有的基础上增加了文件上传与下载模拟功能:

 

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.StringTokenizer;

/**
 * 
 * @author 刘长炯
 * modi by jzj
 *
 */
public class SimpleHttpServer implements Runnable {

	ServerSocket serverSocket;//服务器Socket

	public static int PORT = 80;//标准HTTP端口

	public String encoding = "GBK";

	public SimpleHttpServer() {
		try {
			serverSocket = new ServerSocket(PORT);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
		new Thread(this).start();
		System.out.println("HTTP服务器正在运行,端口:" + PORT);
	}

	public void run() {
		while (true) {
			try {
				Socket client = serverSocket.accept();//客户机(这里是 IE 等浏览器)已经连接到当前服务器
				if (client != null) {
					System.out.println("连接到服务器的用户:" + client);
					try {
						// 第一阶段: 打开输入流
						InputStream is = client.getInputStream();

						System.out.println("客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>");
						// 读取第一行, 请求地址
						String line = readLine(is, 0);
						//打印请求行
						System.out.print(line);
						// < Method > < URL > < HTTP Version > <\r\n>  取的是URL部分
						String resource = line.substring(line.indexOf('/'), line
								.lastIndexOf('/') - 5);
						//获得请求的资源的地址
						resource = URLDecoder.decode(resource, encoding);//反编码 URL 地址
						String method = new StringTokenizer(line).nextElement()
								.toString();// 获取请求方法, GET 或者 POST
						int contentLength = 0;//如果为POST方法,则会有消息体长度

						// 读取所有浏览器发送过来的请求参数头部信息
						do {
							line = readLine(is, 0);
							//如果有Content-Length消息头时取出
							if (line.startsWith("Content-Length")) {
								contentLength = Integer.parseInt(line.split(":")[1]
										.trim());
							}
							//打印请求部信息
							System.out.print(line);
							//如果遇到了一个单独的回车换行,则表示请求头结束
						} while (!line.equals("\r\n"));
						//如果是POST请求,则有请求体
						if ("POST".equalsIgnoreCase(method)) {
							//注,这里只是简单的处理表单提交的参数,而对于上传文件这里是不能这样处理的,
							//因为上传的文件时消息体不只是一行,会有多行消息体
							System.out.print(readLine(is, contentLength));
							System.out.println();
						}

						System.out.println("客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<");
						System.out.println("用户请求的资源是:" + resource);
						System.out.println("请求的类型是: " + method);
						System.out.println();

						//如果是下载文件
						if (resource.startsWith("/download")) {
							fileDownload("test.txt", client);
							closeSocket(client);
							continue;
						}

						// GIF 图片就读取一个真实的图片数据并返回给客户端
						if (resource.endsWith(".gif")) {
							imgDownload("test.gif", client);
							closeSocket(client);
							continue;
						}

						// 请求 JPG 格式就报错 404
						if (resource.endsWith(".jpg")) {
							PrintWriter out = new PrintWriter(client.getOutputStream(),
									true);
							out.println("HTTP/1.0 404 Not found");//返回应答消息,并结束应答
							out.println();// 根据 HTTP 协议, 空行将结束头信息
							out.close();
							closeSocket(client);
							continue;
						} else {
							// 用 writer 对客户端 socket 输出一段 HTML 代码
							PrintWriter out = new PrintWriter(client.getOutputStream(),
									true);
							out.println("HTTP/1.0 200 OK");//返回应答消息,并结束应答
							out.println("Content-Type:text/html;charset=" + encoding);
							out.println();// 根据 HTTP 协议, 空行将结束头信息

							out.println("<h1> Hello Http Server</h1>");
							out.println("你好, 这是一个 Java HTTP 服务器 demo 应用.<br>");
							out.println("您请求的路径是: " + resource + "<br>");
							out.println("你请求的页面含有图片:<img src='test.gif'><br>"
									+ "<a href='test.gif'>手动点击打开test.gif图片文件.</a>");
							out.println("<br>服务器不支持jpg格式图片,所以显示XX:"
									+ "<img src='test.jpg'><br><a href='test.jpg'>"
									+ "手动点击打开test.jpg,会跳转另一页面,并且服务返回为404错误</a><br>");
							out
									.println("<form method=post action='/path?qryParm=POST URL查询参数' > POST 表单 "
											+ "<input name=username value='用户'> "
											+ "<input name=submit type=submit value=submit></form>");
							out
									.println("<form method=get action='/path?qryParm=GET URL查询参数' >&nbsp;GET 表单 "
											+ "<input name=username value='用户'> "
											+ "<input name=submit type=submit value=submit></form>");

							out
									.println("<form method=post action='/path?qryParm=POST URL查询参数'"
											+ " enctype='multipart/form-data' >"
											+ "文件上传&nbsp; <input type='file' name=file1 ><br>"
											+ "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "
											+ "<input type='file' name=file2 ><br>"
											+ "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "
											+ "<input name=username value='用户'> "
											+ "<input name=submit type=submit value=submit></form>");
							out.println("<a href='/download'>点击此处模拟文件下载</a>");

							out.close();

							closeSocket(client);
						}
					} catch (Exception e) {
						System.out.println("HTTP服务器错误:" + e.getLocalizedMessage());
					}
				}
				//System.out.println(client+"连接到HTTP服务器");//如果加入这一句,服务器响应速度会很慢
			} catch (Exception e) {
				System.out.println("HTTP服务器错误:" + e.getLocalizedMessage());
			}
		}
	}

	/*
	 * 这里我们自己模拟读取一行,因为如果使用API中的BufferedReader时,它是读取到一个回车换行后
	 * 才返回,否则如果没有读取,则一直阻塞,这就导致如果为POST请求时,表单中的元素会以消息体传送,
	 * 这时,消息体最末按标准是没有回车换行的,如果此时还使用BufferedReader来读时,则POST提交
	 * 时会阻塞。如果是POST提交时我们按照消息体的长度Content-Length来截取消息体,这样就不会阻塞
	 */
	private String readLine(InputStream is, int contentLe) throws IOException {
		ArrayList lineByteList = new ArrayList();
		byte readByte;
		int total = 0;
		if (contentLe != 0) {
			do {
				readByte = (byte) is.read();
				lineByteList.add(Byte.valueOf(readByte));
				total++;
			} while (total < contentLe);//消息体读还未读完
		} else {
			do {
				readByte = (byte) is.read();
				lineByteList.add(Byte.valueOf(readByte));
			} while (readByte != 10);
		}

		byte[] tmpByteArr = new byte[lineByteList.size()];
		for (int i = 0; i < lineByteList.size(); i++) {
			tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
		}
		lineByteList.clear();

		String tmpStr = new String(tmpByteArr, encoding);
		/* http请求的header中有一个Referer属性,这个属性的意思就是如果当前请求是从别的页面链接过
		 * 来的,那个属性就是那个页面的url,如果请求的url是直接从浏览器地址栏输入的就没有这个值。得
		 * 到这个值可以实现很多有用的功能,例如防盗链,记录访问来源以及记住刚才访问的链接等。另外,浏
		 * 览器发送这个Referer链接时好像固定用UTF-8编码的,所以在GBK下出现乱码,我们在这里纠正一下
		 */
		if (tmpStr.startsWith("Referer")) {//如果有Referer头时,使用UTF-8编码
			tmpStr = new String(tmpByteArr, "UTF-8");
		}
		return tmpStr;
	}

	/**
	* 关闭客户端 socket 并打印一条调试信息.
	* @param socket 客户端 socket.
	*/
	void closeSocket(Socket socket) {
		try {
			socket.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
		System.out.println(socket + "离开了HTTP服务器");
	}

	/**
	* 读取一个图像文件的内容并返回给浏览器端.
	* @param fileName 文件名
	* @param socket 客户端 socket.
	*/
	void imgDownload(String fileName, Socket socket) {

		try {
			PrintStream out = new PrintStream(socket.getOutputStream(), true);
			File fileToSend = new File(fileName);
			if (fileToSend.exists() && !fileToSend.isDirectory()) {
				out.println("HTTP/1.0 200 OK");//返回应答消息,并结束应答
				out.println("Content-Type: application/octet-stream");
				out.println("Content-Length: " + fileToSend.length());// 返回内容字节数
				out.println();// 根据 HTTP 协议, 空行将结束头信息

				FileInputStream fis = new FileInputStream(fileToSend);
				byte data[] = new byte[fis.available()];
				fis.read(data);
				out.write(data);
				//文件下载完后关闭socket流,但socket还没有关闭
				out.close();
				fis.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	* 读取一个文件的内容并返回给浏览器端.
	* @param fileName 文件名
	* @param socket 客户端 socket.
	*/
	void fileDownload(String fileName, Socket socket) {
		try {
			PrintStream out = new PrintStream(socket.getOutputStream(), true);
			File fileToSend = new File(fileName);
			if (fileToSend.exists() && !fileToSend.isDirectory()) {
				out.println("HTTP/1.0 200 OK");//返回应答消息,并结束应答
				out.println("Content-Type: application/octet-stream;charset=" + encoding);

				/* Content-Disposition不是标准参数,查看一下HTTP/1.1的规范文档,对于这个参数的解释大意如下:
				 * Content-Disposition参数本来是为了在客户端另存文件时提供一个建议的文件名,但是考虑到安全的原因,
				 * 就从规范中去掉了这个参数。但是由于很多浏览器已经能够支持这个参数,所以只是在规范文档中列出,但是要
				 * 注意这个不是HTTP/1.1的标准参数。其值为“attachment”,那么无论这个文件是何类型,浏览器都会提示我
				 * 们下载此文件,因为此时它认为后面的消息体是一个“附件”,不需要由浏览器来处理了。
				 */
				out.println("Content-Disposition: attachment;filename=测试下载文件.txt");
				//				out.println("Accept-Ranges: bytes");
				out.println("Content-Length: " + fileToSend.length());// 返回内容字节数
				out.println();// 根据 HTTP 协议, 空行将结束头信息

				FileInputStream fis = new FileInputStream(fileToSend);
				byte[] tmpByteArr = new byte[10];//这里为了测试看下载进度条,所以设置小点
				while (fis.available() > 0) {
					int readCount = fis.read(tmpByteArr);
					out.write(tmpByteArr, 0, readCount);
				}

				//文件下载完后关闭socket流
				out.close();
				fis.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		PORT = 8080;
		new SimpleHttpServer();
	}
}

 

下面是我测试的过程:

 

在地址栏输入http://localhost:8080/后显示如下页面:

 

点击“手动点击打开test.gif图片文件. ”连接显示以下图片:

再点击“手动点击打开test.jpg,会跳转另一页面,并且服务返回为404错误”显示以下错误页面:


再点击“点击此处模拟文件下载”显示文件下载框:


 
最后是服务器运行日志,仅供参考:

HTTP服务器正在运行,端口:8080
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56155,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET / HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56155,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56156,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.gif HTTP/1.1
Accept: */*
Referer: http://localhost:8080/
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.gif
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56156,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56157,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.jpg HTTP/1.1
Accept: */*
Referer: http://localhost:8080/
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.jpg
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56157,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56158,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.gif HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost:8080/
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.gif
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56158,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56159,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.jpg HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.jpg
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56159,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56160,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
POST /path?qryParm=POST%20URL查询参数 HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost:8080/
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 35
Connection: Keep-Alive
Cache-Control: no-cache

 

username=%D3%C3%BB%A7&submit=submit
客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/path?qryParm=POST URL查询参数
请求的类型是: POST

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56160,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56161,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.gif HTTP/1.1
Accept: */*
Referer: http://localhost:8080/path?qryParm=POST URL查询参数
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.gif
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56161,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56162,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.jpg HTTP/1.1
Accept: */*
Referer: http://localhost:8080/path?qryParm=POST URL查询参数
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.jpg
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56162,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56163,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /path?username=%D3%C3%BB%A7&submit=submit HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost:8080/path?qryParm=POST URL查询参数
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/path?username=用户&submit=submit
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56163,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56165,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.jpg HTTP/1.1
Accept: */*
Referer: http://localhost:8080/path?username=%D3%C3%BB%A7&submit=submit
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.jpg
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56165,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56164,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.gif HTTP/1.1
Accept: */*
Referer: http://localhost:8080/path?username=%D3%C3%BB%A7&submit=submit
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.gif
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56164,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56168,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
POST /path?qryParm=POST%20URL查询参数 HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost:8080/path?username=%D3%C3%BB%A7&submit=submit
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Content-Type: multipart/form-data; boundary=---------------------------7d91c380444
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 591
Connection: Keep-Alive
Cache-Control: no-cache

 

-----------------------------7d91c380444
Content-Disposition: form-data; name="file1"; filename="file1.txt"
Content-Type: text/plain

 

123
-----------------------------7d91c380444
Content-Disposition: form-data; name="file2"; filename="file2.txt"
Content-Type: text/plain

 

这是第二个测试文件的内容:
中a ~!@#$%^&*()_+{}|:\" <>?`-=[]\\;',./
-----------------------------7d91c380444
Content-Disposition: form-data; name="username"

 

用户
-----------------------------7d91c380444
Content-Disposition: form-data; name="submit"

 

submit
-----------------------------7d91c380444--

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/path?qryParm=POST URL查询参数
请求的类型是: POST

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56168,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56169,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.gif HTTP/1.1
Accept: */*
Referer: http://localhost:8080/path?qryParm=POST URL查询参数
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.gif
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56169,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56170,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /test.jpg HTTP/1.1
Accept: */*
Referer: http://localhost:8080/path?qryParm=POST URL查询参数
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/test.jpg
请求的类型是: GET

 

Socket[addr=/0:0:0:0:0:0:0:1,port=56170,localport=8080]离开了HTTP服务器
连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=56171,localport=8080]
客户端发送的请求信息: >>>>>>>>>>>>>>>>>>>>>>>>>
GET /download HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Referer: http://localhost:8080/path?qryParm=POST URL查询参数
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

 

客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<
用户请求的资源是:/download
请求的类型是: GET

Socket[addr=/0:0:0:0:0:0:0:1,port=56171,localport=8080]离开了HTTP服务器

 

  • 大小: 5.1 KB
  • 大小: 4.4 KB
  • 大小: 20.2 KB
  • 大小: 11.1 KB
分享到:
评论
1 楼 biboyuzhou 2015-08-20  
楼主你好,有个问题小弟没有搞明白。我只访问了一次localhost:8080,为什么会打印了这么多次连接到服务器的用户:Socket[addr=/0:0:0:0:0:0:0:1,port=60569,localport=8080]?
意思就是socket链接到localhost链接了好多次呢?

相关推荐

    Java_Socket现实简单的HTTP服务

    ### Java Socket实现简单HTTP服务详解 #### 知识点概览 本文将深入解析如何使用Java的Socket编程技术实现一个简易的HTTP服务器。这不仅涵盖了基础的请求与响应流程,还涉及了状态码的处理、不同类型的响应内容(如...

    JAVA-socket开发指南

    #### 七、Socket在现实世界的应用 Socket不仅用于简单的文本数据传输,还可以应用于多种复杂场景,如: - **Web服务器:** 通过HTTP协议处理客户端的请求。 - **游戏服务器:** 实现玩家之间的实时互动。 - **...

    socket概念socket概念socket概念

    Socket 的工作原理类似于现实生活中电话系统的运作方式。每个Socket都有一个唯一的标识,就像电话号码一样,通过这个标识,两个Socket之间可以建立连接并交换数据。在TCP/IP协议栈中,Socket 分为两部分:服务器端...

    HP-Socket文档

    应用程序可以根据不同的容量要求、通信规模和资源状况等现实场景调整 HP-Socket 的各项性能参数(如:工作线程的数量、缓存池的大小、发送模式和接收模式等),优化资源配置,在满足应用需求的同时不必过度浪费资源...

    java课件——全面介绍java知识

    Java的Socket类和ServerSocket类用于创建TCP连接,HttpURLConnection类则用于HTTP请求。 线程和并发处理是多任务环境下的必备知识。Java提供了Thread类和Runnable接口来创建和管理线程,同时还有synchronized关键字...

    【Java毕业设计】毕业设计——基于Java的漏洞扫描系统.zip

    3. **HTTP协议与Web服务**:为了扫描Web应用的漏洞,系统可能需要发送HTTP请求,解析响应,这需要对HTTP协议有深入理解。可能使用了HttpURLConnection或HttpClient库。 4. **数据解析与XML/JSON**:在获取服务器...

    HP-Socket Development Guide5.6.pdf

    HP-Socket框架具有良好的伸缩性,用户可以根据不同的容量要求、通信规模和资源状况等现实场景调整其性能参数,如工作线程的数量、缓存池的大小、发送模式和接收模式等,以优化资源配置,并满足应用需求而不必过度...

    an introduction to network programming with java

    使用这些类,开发者可以构建复杂的网络应用程序,实现从简单的客户端-服务器模型到分布式系统和Web服务。 网络编程的实践过程中,还需要注意异常处理和资源管理。网络连接很容易受到网络问题的影响,比如网络延迟、...

    java火车售票系统

    - **Socket编程**:如果该系统设计为网络应用,那么需要使用Java的Socket编程实现客户端与服务器之间的通信,处理用户的请求和响应。 - **HTTP协议**:基于Web的售票系统可能会使用HTTP协议进行数据传输,理解HTTP...

    java语言程序设计案例教程

    网络编程部分,读者将学习如何利用Java的Socket编程来创建客户端和服务器应用。这可能包括TCP和UDP通信的示例,以及HTTP协议的应用。 最后,I/O流是Java处理输入输出的重要模块,包括文件操作、对象序列化和网络...

    java程序设计课件

    在课件中,你可能会学到如何创建一个简单的Java应用程序,包括定义类、对象、变量和方法。类是Java中的基本构造块,它封装了数据和操作这些数据的方法。对象则是类的实例,它们代表现实世界中的实体或概念。 "继承...

    java技术文档

    了解这些概念有助于理解Java如何模拟现实世界中的实体,以及如何通过对象间的交互实现复杂的功能。 4. **第05章 Java的数据结构**:数据结构是有效组织和存储数据的方式。此章可能涉及数组、链表、栈、队列、集合...

    java代码大全 有用的下载

    8. **网络编程**: Java的Socket和ServerSocket类提供了TCP/IP通信能力,而URL和URLConnection则支持HTTP、FTP等协议的网络访问。 9. **反射机制**: 反射允许程序在运行时动态地获取类的信息(如类名、方法名)并...

    Java 局域网聊天源码

    Java语言提供了Socket编程接口,可以用于实现网络上的数据传输。在这个聊天程序中,客户端和服务器端通过Socket建立连接,进行双向通信。客户端发送消息到服务器,服务器接收并广播这些消息给其他在线的客户端。这种...

    Java语言程序设计(源代码)

    Java提供Socket和ServerSocket类来进行TCP/IP网络通信,URL和URLConnection类用于HTTP访问。源代码中可能有实现简单网络应用的示例。 10. **Java标准库** Java标准库(Java API)包含大量预定义的类和接口,如IO...

    Java网络开发[借鉴].pdf

    本文主要讨论Java中的套接字(Socket)概念及其在网络编程中的应用。 1. **IP地址**:IP地址是互联网上的每台计算机的唯一标识,类似于现实世界的电话号码。它由四个以小数点分隔的十进制数字组成,每个部分的数值...

    用java做的一个毕业设计

    Java的Socket编程允许开发者创建TCP/IP连接,实现数据的发送和接收。此外,HTTPS、FTP等网络协议也可能在项目中得到应用,以实现安全的数据传输或文件共享。 五、异常处理与单元测试 为了确保代码的健壮性,开发者...

    Java 编程课后答案 双语教学

    7. **网络编程**:Socket编程,包括客户端和服务端的建立连接、数据传输,以及HTTP协议的简单实现。 8. **泛型**:理解泛型的基本概念,如何使用泛型类、泛型方法,以及泛型通配符的应用。 9. **反射**:Java反射...

    Java 2 教程(第五版)(PDG).rar

    12. **Java API**:Java 2平台提供了大量的API,如JavaMail、JMS(Java消息服务)、JAXP(Java API for XML Processing)等,用于处理邮件、消息传递、XML解析等功能。 13. **JDK v1.4的新特性**:这一版本引入了...

    Java基础篇:网络编程.pdf

    其中0到1023是公认端口,通常被系统级服务占用,比如HTTP服务占用80端口,FTP服务占用21端口等。注册端口范围从1024到49151,这些端口被分配给用户进程或应用程序使用,例如Tomcat服务器通常使用8080端口。动态或...

Global site tag (gtag.js) - Google Analytics