HTTPClient程序(HTTPClient.java):
package client;
import java.net.*;
import java.io.*;
import java.util.*;
public class HTTPClient {
public static void main(String args[]){
//确定HTTP请求的uri
String uri="index.htm";
if(args.length !=0)uri=args[0];
doGet("localhost",8080,uri); //按照GET请求方式访问HTTPServer
}
/** 按照GET请求方式访问HTTPServer */
public static void doGet(String host,int port,String uri){
Socket socket=null;
try{
socket=new Socket(host,port); //与HTTPServer建立FTP连接
}catch(Exception e){e.printStackTrace();}
try{
/*创建HTTP请求 */
StringBuffer sb=new StringBuffer("GET "+uri+" HTTP/1.1\r\n");
sb.append("Accept: */*\r\n");
sb.append("Accept-Language: zh-cn\r\n");
sb.append("Accept-Encoding: gzip, deflate\r\n");
sb.append("User-Agent: HTTPClient\r\n");
sb.append("Host: localhost:8080\r\n");
sb.append("Connection: Keep-Alive\r\n\r\n");
/*发送HTTP请求*/
OutputStream socketOut=socket.getOutputStream(); //获得输出流
socketOut.write(sb.toString().getBytes());
Thread.sleep(2000); //睡眠2秒,等待响应结果
/*接收响应结果*/
InputStream socketIn=socket.getInputStream(); //获得输入流
int size=socketIn.available();
byte[] buffer=new byte[size];
socketIn.read(buffer);
System.out.println(new String(buffer)); //打印响应结果
}catch(Exception e){
e.printStackTrace();
}finally{
try{
socket.close();
}catch(Exception e){e.printStackTrace();}
}
} //#doGet()
}
HTTPServer程序(HTTPServer.java)
package server;
import java.io.*;
import java.net.*;
public class HTTPServer{
public static void main(String args[]) {
int port;
ServerSocket serverSocket;
try {
port = Integer.parseInt(args[0]);
}catch (Exception e) {
System.out.println("port = 8080 (默认)");
port = 8080; //默认端口为8080
}
try{
serverSocket = new ServerSocket(port);
System.out.println("服务器正在监听端口:"
+ serverSocket.getLocalPort());
while(true) { //服务器在一个无限循环中不断接收来自客户的TCP连接请求
try{
//等待客户的TCP连接请求
final Socket socket = serverSocket.accept();
System.out.println("建立了与客户的一个新的TCP连接,"
+"该客户的地址为:"
+socket.getInetAddress()+":" + socket.getPort());
service(socket); //响应客户请求
}catch(Exception e){
System.out.println("客户端请求的资源不存在");}
} //#while
}catch (Exception e) {e.printStackTrace();}
}
/** 响应客户的HTTP请求 */
public static void service(Socket socket)throws Exception{
/*读取HTTP请求信息*/
InputStream socketIn=socket.getInputStream(); //获得输入流
Thread.sleep(500); //睡眠500毫秒,等待HTTP请求
int size=socketIn.available();
byte[] buffer=new byte[size];
socketIn.read(buffer);
String request=new String(buffer);
System.out.println(request); //打印HTTP请求数据
/*解析HTTP请求*/
//获得HTTP请求的第一行
int endIndex=request.indexOf("\r\n");
if(endIndex==-1)
endIndex=request.length();
String firstLineOfRequest=
request.substring(0,endIndex);
//解析HTTP请求的第一行
String[] parts=firstLineOfRequest.split(" ");
String uri="";
if(parts.length>=2)
uri=parts[1]; //获得HTTP请求中的uri
/*决定HTTP响应正文的类型,此处作了简化处理*/
String contentType;
if(uri.indexOf("html")!=-1 || uri.indexOf("htm")!=-1)
contentType="text/html";
else if(uri.indexOf("jpg")!=-1 || uri.indexOf("jpeg")!=-1)
contentType="image/jpeg";
else if(uri.indexOf("gif")!=-1)
contentType="image/gif";
else
contentType="application/octet-stream"; //字节流类型
/*创建HTTP响应结果 */
//HTTP响应的第一行
String responseFirstLine="HTTP/1.1 200 OK\r\n";
//HTTP响应头
String responseHeader="Content-Type:"+contentType+"\r\n\r\n";
//获得读取响应正文数据的输入流
InputStream in=HTTPServer
.class
.getResourceAsStream("root/"+uri);
/*发送HTTP响应结果 */
OutputStream socketOut=socket.getOutputStream(); //获得输出流
//发送HTTP响应的第一行
socketOut.write(responseFirstLine.getBytes());
//发送HTTP响应的头
socketOut.write(responseHeader.getBytes());
//发送HTTP响应的正文
int len=0;
buffer=new byte[128];
while((len=in.read(buffer))!=-1)
socketOut.write(buffer,0,len);
Thread.sleep(1000); //睡眠1秒,等待客户接收HTTP响应结果
socket.close(); //关闭TCP连接
}
}
1. HTTPClient程序与HTTPServer程序通信:
将源程序编译成.class文件后,分别在HTTPClient.class与HTTPServer.class根目录(由于源代码有package声明,所以其根目录为client或server目录的上一级,同理执行java 命令时class文件也应该带包前缀,如java server.HTTPServer
)下进入DOS(disk operate system)窗口,分别执行命令 java server.HTTPServer
java client.HTTPClient 'root目录下文件名'
, 以运行HTTP服务端程序与HTTP客户端程序。客户端的请求文件如果默认的话为请求/root/index.htm文件(请求文件需要放在server包下的root目录中,即server/root/请求文件。启动后界面如下:
服务端程序启动:
客户端程序启动并请求(默认/root/index.htm):
服务端程序响应客户端请求:
注意:直接通过源程序重新编译生成的.class文件运行一般不会有问题。如果不是直接在本地编译生成的class文件,而是从其他地方直接获取到的,在DOS窗口直接运行时可能会报以下错误:Error: A JNI error has occurred, please check your installation and try again
:原因是由于电脑上可能有多个版本的JDK,通过卸载旧版本的JDK,使java -version
与 javac -version
一致即可。当然,这种情况是你在通过本地直接编译生成class文件仍报错的情况。如果你本地本来编译与运行版本本来就一致的话,也就无需要进行卸载了,只需要重新使用javac命令编译源文件,再重新运行即可。
2. 浏览器访问HTTPServer程序:
保持DOS窗口HTTPServer程序运行,在浏览器输入http://localhost:8080/hello6.htm
即可。此时服务端窗口响应如下:
有些浏览器可能会发出多个请求,不仅包含目标文件,也可能发出一些与服务器内部通信的请求,如果这些资源不存在,服务端程序会返回"客户端请求的资源不存在"提示.
3. HTTPClient程序访问TOMCAT服务器:
关闭HTTPServer程序。在tomcat安装目录的bin目录下,通过startup.bat
或者catalina run
命令启动TOMCAT.(没安装得先安装下):
未关闭HTTPServer程序启动TOMCAT时会报以下错误:
这是由于同一台主机中不允许多个服务器进程监听同一个端口,而在HTTPServer程序及TOMCAT中都监听了8080端口,因此不能在同一台主机中同时启动它们。
4. 浏览器访问TOMCAT服务器:
TOMCAT服务器启动后,浏览器输入http://localhost:8080/index.jsp
,即可展示TOMCAT 索引页。
综上,这些所有异构系统之前请求与响应的通信,都是基于遵守共同的HTTP协议实现的。
参考文档:Tomcat与Java Web开发技术详解
www.javathinker.net