您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Java實(shí)現(xiàn)Http協(xié)議的方法”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Java實(shí)現(xiàn)Http協(xié)議的方法”吧!
Java 實(shí)現(xiàn)Http協(xié)議
一、協(xié)議請(qǐng)求的定義
二、響應(yīng)協(xié)議的定義
三、編碼常量定義
四、客戶端的實(shí)現(xiàn)
五、服務(wù)端的實(shí)現(xiàn)
六、ProtocolUtils工具類的實(shí)現(xiàn)
七、ByteUtils類的實(shí)現(xiàn)
HTTP協(xié)議屬于應(yīng)用層協(xié)議,它構(gòu)建于TCP和IP協(xié)議之上,處于TCP/IP協(xié)議架構(gòu)層的頂端,所以,它不用處理下層協(xié)議間諸如丟包補(bǔ)發(fā)、握手及數(shù)據(jù)的分段及重新組裝等繁瑣的細(xì)節(jié),使開發(fā)人員可以專注于應(yīng)用業(yè)務(wù)。
協(xié)議是通信的規(guī)范,為了更好的理解HTTP協(xié)議,我們可以基于Java的Socket API接口,通過(guò)設(shè)計(jì)一個(gè)簡(jiǎn)單的應(yīng)用層通信協(xié)議,來(lái)簡(jiǎn)單分析下協(xié)議實(shí)現(xiàn)的過(guò)程和細(xì)節(jié)。
在我們今天的示例程序中,客戶端會(huì)向服務(wù)端發(fā)送一條命令,服務(wù)端在接收到命令后,會(huì)判斷命令是否是“HELLO”,如果是“HELLO”, 則服務(wù)端返回給客戶端的響應(yīng)為“hello”,否則,服務(wù)端返回給客戶端的響應(yīng)為“bye bye”。
我們接下來(lái)用Java實(shí)現(xiàn)這個(gè)簡(jiǎn)單的應(yīng)用層通信協(xié)議,
協(xié)議的請(qǐng)求主要包括:編碼、命令和命令長(zhǎng)度三個(gè)字段。
package com.binghe.params; /** * 協(xié)議請(qǐng)求的定義 * @author binghe * */ public class Request { /** * 協(xié)議編碼 */ private byte encode; /** * 命令 */ private String command; /** * 命令長(zhǎng)度 */ 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 + "]"; } }
協(xié)議的響應(yīng)主要包括:編碼、響應(yīng)內(nèi)容和響應(yīng)長(zhǎng)度三個(gè)字段。
package com.binghe.params; /** * 協(xié)議響應(yīng)的定義 * @author binghe * */ public class Response { /** * 編碼 */ private byte encode; /** * 響應(yīng)內(nèi)容 */ private String response; /** * 響應(yīng)長(zhǎng)度 */ 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; }
客戶端先構(gòu)造一個(gè)request請(qǐng)求,通過(guò)Socket接口將其發(fā)送到遠(yuǎn)端,并接收遠(yuǎn)端的響應(yīng)信息,并構(gòu)造成一個(gè)Response對(duì)象。
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{ //請(qǐng)求 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(); //發(fā)送請(qǐng)求 ProtocolUtils.writeRequest(out, request); //讀取響應(yīng)數(shù)據(jù) InputStream in = client.getInputStream(); Response response = ProtocolUtils.readResponse(in); System.out.println("獲取的響應(yīng)結(jié)果信息為: " + response.toString()); } }
服務(wù)端接收客戶端的請(qǐng)求,根據(jù)接收命令的不同,響應(yīng)不同的消息信息,如果是“HELLO”命令,則響應(yīng)“hello”信息,否則響應(yīng)“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(); //讀取請(qǐng)求數(shù)據(jù) InputStream input = client.getInputStream(); Request request = ProtocolUtils.readRequest(input); System.out.println("收到的請(qǐng)求參數(shù)為: " + request.toString()); OutputStream out = client.getOutputStream(); //組裝響應(yīng)數(shù)據(jù) 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
的readRequest
方法將從傳遞進(jìn)來(lái)的輸入流中讀取請(qǐng)求的encode
、command
和commandLength
三個(gè)參數(shù),進(jìn)行相應(yīng)的編碼轉(zhuǎn)化,構(gòu)造成Request
對(duì)象返回。而writeResponse
方法則是將response
對(duì)象的字段根據(jù)對(duì)應(yīng)的編碼寫入到響應(yīng)的輸出流中。
有一個(gè)細(xì)節(jié)需要重點(diǎn)注意:OutputStream
中直接寫入一個(gè)int類型,會(huì)截取其低8位,丟棄其高24位,所以,在傳遞和接收數(shù)據(jù)時(shí),需要進(jìn)行相應(yīng)的轉(zhuǎn)化操作。
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; /** * 協(xié)議工具類 * @author binghe * */ public final class ProtocolUtils { /** * 從輸入流中反序列化Request對(duì)象 * @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]; //讀取命令長(zhǎng)度 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"); } //組裝請(qǐng)求返回 Request request = new Request(encode, command, commandLength); return request; } /** * 從輸入流中反序列化Response對(duì)象 * @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]; //讀取響應(yīng)長(zhǎng)度 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"); } //組裝請(qǐng)求返回 Response resp = new Response(encode, response, responseLength); return resp; } /** * 序列化請(qǐng)求信息 * @param output * @param response */ public static void writeRequest(OutputStream output, Request request) throws IOException{ //將response響應(yīng)返回給客戶端 output.write(request.getEncode()); //output.write(response.getResponseLength());直接write一個(gè)int類型會(huì)截取低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(); } /** * 序列化響應(yīng)信息 * @param output * @param response */ public static void writeResponse(OutputStream output, Response response) throws IOException{ //將response響應(yīng)返回給客戶端 output.write(response.getEncode()); //output.write(response.getResponseLength());直接write一個(gè)int類型會(huì)截取低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(); } }
package com.binghe.utils; /** * 字節(jié)轉(zhuǎn)化工具類 * @author binghe * */ public final class ByteUtils { /** * 將byte數(shù)組轉(zhuǎn)化為int數(shù)字 * @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類型數(shù)字轉(zhuǎn)化為byte數(shù)組 * @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; } }
到此,相信大家對(duì)“Java實(shí)現(xiàn)Http協(xié)議的方法”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。