千家信息网

Java实现Http协议的方法

发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,本篇内容主要讲解"Java实现Http协议的方法",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java实现Http协议的方法"吧!目录Java 实现Htt
千家信息网最后更新 2025年01月16日Java实现Http协议的方法

本篇内容主要讲解"Java实现Http协议的方法",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java实现Http协议的方法"吧!

目录
  • Java 实现Http协议

    • 一、协议请求的定义

    • 二、响应协议的定义

    • 三、编码常量定义

    • 四、客户端的实现

    • 五、服务端的实现

    • 六、ProtocolUtils工具类的实现

    • 七、ByteUtils类的实现

HTTP协议属于应用层协议,它构建于TCP和IP协议之上,处于TCP/IP协议架构层的顶端,所以,它不用处理下层协议间诸如丢包补发、握手及数据的分段及重新组装等繁琐的细节,使开发人员可以专注于应用业务。

协议是通信的规范,为了更好的理解HTTP协议,我们可以基于Java的Socket API接口,通过设计一个简单的应用层通信协议,来简单分析下协议实现的过程和细节。

在我们今天的示例程序中,客户端会向服务端发送一条命令,服务端在接收到命令后,会判断命令是否是"HELLO",如果是"HELLO", 则服务端返回给客户端的响应为"hello",否则,服务端返回给客户端的响应为"bye bye"。

我们接下来用Java实现这个简单的应用层通信协议,

一、协议请求的定义

协议的请求主要包括:编码、命令和命令长度三个字段。

package com.binghe.params;/** * 协议请求的定义 * @author binghe * */public class Request { /**  * 协议编码  */ private byte encode;  /**  * 命令  */ private String command;  /**  * 命令长度  */ private int commandLength; public Request() {  super(); } public Request(byte encode, String command, int commandLength) {  super();  this.encode = encode;  this.command = command;  this.commandLength = commandLength; } public byte getEncode() {  return encode; } public void setEncode(byte encode) {  this.encode = encode; } public String getCommand() {  return command; } public void setCommand(String command) {  this.command = command; } public int getCommandLength() {  return commandLength; } public void setCommandLength(int commandLength) {  this.commandLength = commandLength; } @Override public String toString() {  return "Request [encode=" + encode + ", command=" + command    + ", commandLength=" + commandLength + "]"; } }

二、响应协议的定义

协议的响应主要包括:编码、响应内容和响应长度三个字段。

package com.binghe.params;/** * 协议响应的定义 * @author binghe * */public class Response { /**  * 编码  */ private byte encode;  /**  * 响应内容  */ private String response;  /**  * 响应长度  */ private int responseLength; public Response() {  super(); } public Response(byte encode, String response, int responseLength) {  super();  this.encode = encode;  this.response = response;  this.responseLength = responseLength; } public byte getEncode() {  return encode; } public void setEncode(byte encode) {  this.encode = encode; } public String getResponse() {  return response; } public void setResponse(String response) {  this.response = response; } public int getResponseLength() {  return responseLength; } public void setResponseLength(int responseLength) {  this.responseLength = responseLength; } @Override public String toString() {  return "Response [encode=" + encode + ", response=" + response    + ", responseLength=" + responseLength + "]"; } }

三、编码常量定义

编码常量的定义主要包括UTF-8和GBK两种编码。

package com.binghe.constant;/** * 常量类 * @author binghe * */public final class Encode { //UTF-8编码 public static final byte UTF8 = 1; //GBK编码 public static final byte GBK = 2;}

四、客户端的实现

客户端先构造一个request请求,通过Socket接口将其发送到远端,并接收远端的响应信息,并构造成一个Response对象。

package com.binghe.protocol.client;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import com.binghe.constant.Encode;import com.binghe.params.Request;import com.binghe.params.Response;import com.binghe.utils.ProtocolUtils;/** * 客户端代码 * @author binghe * */public final class Client { public static void main(String[] args) throws IOException{  //请求  Request request = new Request();  request.setCommand("HELLO");  request.setCommandLength(request.getCommand().length());  request.setEncode(Encode.UTF8);    Socket client = new Socket("127.0.0.1", 4567);  OutputStream out = client.getOutputStream();    //发送请求  ProtocolUtils.writeRequest(out, request);    //读取响应数据  InputStream in = client.getInputStream();  Response response = ProtocolUtils.readResponse(in);  System.out.println("获取的响应结果信息为: " + response.toString()); }}

五、服务端的实现

服务端接收客户端的请求,根据接收命令的不同,响应不同的消息信息,如果是"HELLO"命令,则响应"hello"信息,否则响应"bye bye"信息。

package com.binghe.protocol.server;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import com.binghe.constant.Encode;import com.binghe.params.Request;import com.binghe.params.Response;import com.binghe.utils.ProtocolUtils;/** * Server端代码 * @author binghe * */public final class Server { public static void main(String[] args) throws IOException{  ServerSocket server = new ServerSocket(4567);  while (true) {   Socket client = server.accept();   //读取请求数据   InputStream input = client.getInputStream();   Request request = ProtocolUtils.readRequest(input);   System.out.println("收到的请求参数为: " + request.toString());   OutputStream out = client.getOutputStream();   //组装响应数据   Response response = new Response();   response.setEncode(Encode.UTF8);   if("HELLO".equals(request.getCommand())){    response.setResponse("hello");   }else{    response.setResponse("bye bye");   }   response.setResponseLength(response.getResponse().length());   ProtocolUtils.writeResponse(out, response);  } }}

六、ProtocolUtils工具类的实现

ProtocolUtilsreadRequest方法将从传递进来的输入流中读取请求的encodecommandcommandLength三个参数,进行相应的编码转化,构造成Request对象返回。而writeResponse方法则是将response对象的字段根据对应的编码写入到响应的输出流中。

有一个细节需要重点注意:OutputStream中直接写入一个int类型,会截取其低8位,丢弃其高24位,所以,在传递和接收数据时,需要进行相应的转化操作。

package com.binghe.utils;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import com.binghe.constant.Encode;import com.binghe.params.Request;import com.binghe.params.Response;/** * 协议工具类 * @author binghe * */public final class ProtocolUtils { /**  * 从输入流中反序列化Request对象  * @param input  * @return  * @throws IOException  */ public static Request readRequest(InputStream input) throws IOException{  //读取编码  byte[] encodeByte = new byte[1];  input.read(encodeByte);  byte encode = encodeByte[0];    //读取命令长度  byte[] commandLengthBytes = new byte[4];  input.read(commandLengthBytes);  int commandLength = ByteUtils.byte2Int(commandLengthBytes);    //读取命令  byte[] commandBytes = new byte[commandLength];  input.read(commandBytes);  String command = "";  if(Encode.UTF8 == encode){   command = new String(commandBytes, "UTF-8");  }else if(Encode.GBK == encode){   command = new String(commandBytes, "GBK");  }  //组装请求返回  Request request = new Request(encode, command, commandLength);  return request; } /**  * 从输入流中反序列化Response对象  * @param input  * @return  * @throws IOException  */ public static Response readResponse(InputStream input) throws IOException{  //读取编码  byte[] encodeByte = new byte[1];  input.read(encodeByte);  byte encode = encodeByte[0];    //读取响应长度  byte[] responseLengthBytes = new byte[4];  input.read(responseLengthBytes);  int responseLength = ByteUtils.byte2Int(responseLengthBytes);    //读取命令  byte[] responseBytes = new byte[responseLength];  input.read(responseBytes);  String response = "";  if(Encode.UTF8 == encode){   response = new String(responseBytes, "UTF-8");  }else if(Encode.GBK == encode){   response = new String(responseBytes, "GBK");  }  //组装请求返回  Response resp = new Response(encode, response, responseLength);  return resp; }  /**  * 序列化请求信息  * @param output  * @param response  */ public static void writeRequest(OutputStream output, Request request) throws IOException{  //将response响应返回给客户端  output.write(request.getEncode());  //output.write(response.getResponseLength());直接write一个int类型会截取低8位传输丢弃高24位  output.write(ByteUtils.int2ByteArray(request.getCommandLength()));  if(Encode.UTF8 == request.getEncode()){   output.write(request.getCommand().getBytes("UTF-8"));  }else if(Encode.GBK == request.getEncode()){   output.write(request.getCommand().getBytes("GBK"));  }  output.flush(); } /**  * 序列化响应信息  * @param output  * @param response  */ public static void writeResponse(OutputStream output, Response response) throws IOException{  //将response响应返回给客户端  output.write(response.getEncode());  //output.write(response.getResponseLength());直接write一个int类型会截取低8位传输丢弃高24位  output.write(ByteUtils.int2ByteArray(response.getResponseLength()));  if(Encode.UTF8 == response.getEncode()){   output.write(response.getResponse().getBytes("UTF-8"));  }else if(Encode.GBK == response.getEncode()){   output.write(response.getResponse().getBytes("GBK"));  }  output.flush(); }}

七、ByteUtils类的实现

package com.binghe.utils;/** * 字节转化工具类 * @author binghe * */public final class ByteUtils { /**  * 将byte数组转化为int数字  * @param bytes  * @return  */ public static int byte2Int(byte[] bytes){  int num = bytes[3] & 0xFF;  num |= ((bytes[2] << 8) & 0xFF00);  num |= ((bytes[1] << 16) & 0xFF0000);  num |= ((bytes[0] << 24) & 0xFF000000);  return num; }  /**  * 将int类型数字转化为byte数组  * @param num  * @return  */ public static byte[] int2ByteArray(int i){  byte[] result = new byte[4];  result[0]  = (byte)(( i >> 24 ) & 0xFF);  result[1]  = (byte)(( i >> 16 ) & 0xFF);  result[2]  = (byte)(( i >> 8 ) & 0xFF);  result[3]  = (byte)(i & 0xFF);  return result; }}

到此,相信大家对"Java实现Http协议的方法"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0