异构系统之前的HTTP通信
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=newbyte[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/请求文件。启动后界面如下:
服务端程序启动:
![](https://img2023.cnblogs.com/blog/2755468/202307/2755468-20230728135225366-1444573673.png)
客户端程序启动并请求(默认/root/index.htm):
![](https://img2023.cnblogs.com/blog/2755468/202307/2755468-20230728135225508-381090472.png)
服务端程序响应客户端请求:
![](https://img2023.cnblogs.com/blog/2755468/202307/2755468-20230728135225460-819834211.png)
注意:直接通过源程序重新编译生成的.class文件运行一般不会有问题。如果不是直接在本地编译生成的class文件,而是从其他地方直接获取到的,在DOS窗口直接运行时可能会报以下错误:Error: A JNI error has occurred, please check your installation and try again
:原因是由于电脑上可能有多个版本的JDK,通过卸载旧版本的JDK,使java -version
与 javac -version
一致即可。当然,这种情况是你在通过本地直接编译生成class文件仍报错的情况。如果你本地本来编译与运行版本本来就一致的话,也就无需要进行卸载了,只需要重新使用javac命令编译源文件,再重新运行即可。
![](https://img2023.cnblogs.com/blog/2755468/202307/2755468-20230728135225526-1239192987.png)
2. 浏览器访问HTTPServer程序:
保持DOS窗口HTTPServer程序运行,在浏览器输入http://localhost:8080/hello6.htm
即可。此时服务端窗口响应如下:
![](https://img2023.cnblogs.com/blog/2755468/202307/2755468-20230728135225490-1834617923.png)
有些浏览器可能会发出多个请求,不仅包含目标文件,也可能发出一些与服务器内部通信的请求,如果这些资源不存在,服务端程序会返回"客户端请求的资源不存在"提示.
3. HTTPClient程序访问TOMCAT服务器:
关闭HTTPServer程序。在tomcat安装目录的bin目录下,通过startup.bat
或者catalina run
命令启动TOMCAT.(没安装得先安装下):
![](https://img2023.cnblogs.com/blog/2755468/202307/2755468-20230728135225467-2126845868.png)
未关闭HTTPServer程序启动TOMCAT时会报以下错误:
![](https://img2023.cnblogs.com/blog/2755468/202307/2755468-20230728135225527-1105924522.png)
这是由于同一台主机中不允许多个服务器进程监听同一个端口,而在HTTPServer程序及TOMCAT中都监听了8080端口,因此不能在同一台主机中同时启动它们。
4. 浏览器访问TOMCAT服务器:
TOMCAT服务器启动后,浏览器输入http://localhost:8080/index.jsp
,即可展示TOMCAT 索引页。
综上,这些所有异构系统之前请求与响应的通信,都是基于遵守共同的HTTP协议实现的。