Reprint Please specify source: http://blog.csdn.net/l1028386804/article/details/52531185
Today, to bring you a slightly deeper article-"RPC--http protocol stack", OK, let's get to the point.
The HTTP protocol belongs to the application-layer protocol, which is built on top of TCP and IP protocols, and it is located at the end of the architecture layer, so it does not deal with the cumbersome details such as packet replacement, handshake, fragmentation and reassembly of data, so that developers can focus on the application business.
Protocol is the specification of communication, in order to better understand the HTTP protocol, we can be based on the Java Socket API interface, through the design of a simple application layer communication protocol, to simple analysis of the implementation of the Protocol process and details.
In our example program today, the client sends a command to the server that, after receiving the command, determines whether the command is "Hello" and, if it is "hello", the response of the server to the client is "hello", otherwise the response returned by the server to the client is "Bye bye ”。
We then use Java to implement this simple application-layer communication protocol:
1. Definition of the Protocol request
The Protocol's requests mainly include: encoding, command, and command length three fields.
Package com.lyz.params;/** * Protocol Request definition * @author Liuyazhuang * */public class Request {/** * protocol encoded */private byte encode;/** * Command */private String command;/** * command length */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;} @Overridepublic String toString () {return "Request [encode=" + Encode + ", command=" + command+ ", commandlength=" + comma Ndlength + "]";}}
2. Definition of response protocol
The response of the Protocol mainly includes: encoding, response content and response length of three fields.
package com.lyz.params;/** * Definition of protocol response * @author Liuyazhuang * */public class Response {/** * encode */private byte encode;/** * Response content */ Private String response;/** * response length */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;} @Overridepublic String toString () {return "Response [encode=" + Encode + ", response=" + response+ ", responselength=" + R Esponselength + "]";}}
3. Definition of coded constants
The definition of coded constants mainly includes UTF-8 and GBK two kinds of coding.
Package com.lyz.constant;/** * Constant class * @author Liuyazhuang * */public final class Encode {//utf-8 encoded public static final byte UTF8 = 1;//GBK encoded public static final byte GBK = 2;}
4, the implementation of the client
The client constructs a request, sends it to the remote through the socket interface, and receives the remote response information and constructs a response object.
Package Com.lyz.protocol.client;import Java.io.ioexception;import Java.io.inputstream;import java.io.OutputStream; Import Java.net.socket;import com.lyz.constant.encode;import Com.lyz.params.request;import com.lyz.params.Response Import com.lyz.utils.protocolutils;/** * Client code * @author Liuyazhuang * */public Final class Client {public static void Ma In (string[] args) throws ioexception{//requests 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 ();// Send Request Protocolutils.writerequest (out, request);//Read response data InputStream in = Client.getinputstream (); Response Response = Protocolutils.readresponse (in); SYSTEM.OUT.PRINTLN ("Get response result information is:" + response.tostring ());}}
5, the implementation of the service side
The server receives a request from the client, responds to different message information depending on the receive command, and responds with "Hello" if the "hello" command otherwise responds to "Bye Bye" information.
Package Com.lyz.protocol.server;import Java.io.ioexception;import Java.io.inputstream;import java.io.OutputStream; Import Java.net.serversocket;import java.net.socket;import com.lyz.constant.encode;import com.lyz.params.Request; Import Com.lyz.params.response;import com.lyz.utils.protocolutils;/** * server-side code * @author Liuyazhuang * */public final Class Server {public static void main (string[] args) throws Ioexception{serversocket Server = new ServerSocket (4567); (true) {Socket client = server.accept ();//Read request data InputStream input = Client.getinputstream (); Request Request = Protocolutils.readrequest (input); SYSTEM.OUT.PRINTLN ("Request parameter Received:" + request.tostring ()); OutputStream out = Client.getoutputstream ();//Assembly Response data 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);}}}
6, the realization of Protocolutils tool class
Protocolutils's Readrequest method reads the requested encode, command, and commandlength three parameters from the input stream that is passed in, making the corresponding encoding conversion and constructing the request object to return. The Writeresponse method, in turn, writes the fields of the response object to the output stream of the response according to the corresponding encoding.
There is one detail that needs to be emphasized: writing an int type directly in the OutputStream will intercept its low 8 bits and discard its high 24 bits, so the corresponding conversion action is required when the data is passed and received.
Package Com.lyz.utils;import Java.io.ioexception;import Java.io.inputstream;import java.io.outputstream;import Com.lyz.constant.encode;import Com.lyz.params.request;import com.lyz.params.response;/** * Protocol Tool class * @author Liuyazhuang * */public Final class Protocolutils {/** * Deserialize the request object from the input stream * @param input * @return * @throws IOException */public static Request readrequest (InputStream input) throws ioexception{//read encoding byte[] Encodebyte = new Byte[1]; Input.read (encodebyte); byte encode = encodebyte[0];//Read command length byte[] commandlengthbytes = new Byte[4];input.read ( commandlengthbytes); int commandlength = Byteutils.byte2int (commandlengthbytes);//Read command 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");} Assembly requests return Request request = new request (encode, command, commandlength); return request;} /** * Deserialize the response object from the input stream * @parAM Input * @return * @throws ioexception */public static Response readresponse (InputStream input) throws ioexception{//read Code byte[] Encodebyte = new Byte[1];input.read (encodebyte); byte encode = encodebyte[0];//Read response length byte[] Responselengthbytes = new Byte[4];input.read (responselengthbytes); int responselength = Byteutils.byte2int (responselengthbytes);// Read command 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");} Assembly request returned Response resp = new Response (encode, Response, responselength); return resp;} /** * Serialization Request Information * @param output * @param response */public static void Writerequest (OutputStream output, request request) th Rows ioexception{//Returns the response response to the client Output.write (Request.getencode ());//output.write (response.getresponselength ()); direct write an int type intercepts the low 8-bit transmit drop high 24-bit 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 ();} /** * Serialization of response information * @param output * @param response */public static void Writeresponse (OutputStream output, response response) Throws ioexception{//returns the response response to the client Output.write (Response.getencode ());//output.write ( Response.getresponselength ()); direct write an int type intercepts a low 8-bit transfer drop high 24-bit 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 ();}}
7, the realization of Byteutils class
Package com.lyz.utils;/** * Byte conversion tool class * @author Liuyazhuang * */public final class Byteutils {/** * Converts a byte array to an int number * @param Bytes * @return */public static int byte2int (byte[] bytes) {int num = bytes[3] & 0xff;num |= ((bytes[2] << 8) &A mp 0XFF00) Num |= ((bytes[1] <<) & 0xFF0000), Num |= ((bytes[0] <<) & 0xff000000); return num;} /** * Convert int type number to byte array * @param num * @return */public static byte[] Int2bytearray (int i) {byte[] result = new Byte[4];res Ult[0] = (byte) ((I >>) & 0xFF); result[1] = (byte) ((I >> +) & 0xFF); result[2] = (by TE) ((I >> 8) & 0xFF); result[3] = (byte) (I & 0xFF); return result;}}
At this point, we have developed the application-Layer Communication protocol sample code.
RPC's--HTTP protocol stack