1. Development environment
1.Protocol version: 3.9 (latest available) Download Address
2.Protocol Protocol Version: 3
3. Ordinary java environment, source code is 2 classes.
This is mainly about instant messaging using the native Java Socket API with its previous and back-end.Then binary data (Bytes) is generated from ProtocolBuf
) For network interaction, the code is easy to understand, suitable for getting started with instant messaging.Real projects start with a mature framework like nio, but the underlying principles are the same.(such as using Netty)
2. protocol Agreement Document
Front End Request Protocol File
syntax = "proto3"; option java_package = "com.asframe.pb3demo.proto"; option java_outer_classname = "LoginRequest"; message LoginReq { //Logon Type int32 type = 1; //Name string name = 2; //Password string pass = 3; }
Server-side return protocol file
syntax = "proto3"; option java_package = "com.asframe.pb3demo.proto"; option java_outer_classname = "LoginResponse"; message LoginRep { //Logon Results int32 result = 1; string msg = 2; }
Note that the protocol architecture of Protocolbuf does not have a certain front-end and back-end.This is also a good place to manage by making a distinction between before and after protocols based on naming.You can also synthesize a file.
Execute the build corresponding structure instructions:
protoc -I=proto --java_out=src login_rep_msg.proto login_req_msg.proto
Generate corresponding java code from protocol file
3. Code
The code is simple and the comments are clear, so you can paste the code directly.
Anxious students can also download the source directly first
Front End Code:
/** * Client Connection Test Example * @author sodaChen * @date 2019.07.06 */ public class Client { public static void main(String[] args) throws Exception { //Front-end socket link Socket socket = new Socket("localhost", 19000); // Read DataInputStream from the server side DataInputStream in = new DataInputStream(socket.getInputStream()); // DataOutputStream that sends information to the server DataOutputStream out = new DataOutputStream(socket.getOutputStream()); //Construct a LoginReq object LoginRequest.LoginReq loginReq = LoginRequest.LoginReq.newBuilder() .setType(1) .setName("soda") .setPass("123456") .build(); //Convert to bytes to calculate the size of pb protocol sent byte[] bodyBytes = loginReq.toByteArray(); //Define the message body (message body content + previous version number size) out.writeShort(bodyBytes.length + 4); //Write version number out.writeShort(1); //Message directive, message directive is unique, return directive is 10000 more than send directive, that is 20001 out.writeShort(10001); //Write message body out.write(bodyBytes); out.flush(); //Receive server data here. Resolve the send protocol flow of the server, basically the client sends to the server similar //Receive message length size first short msgLength = in.readShort(); //Message directives short cmd = in.readShort(); //The remaining bytes are message bodies byte[] bytes = new byte[msgLength - 2]; in.read(bytes); //This specifies that the server returns a protocol number of more than 1w.Actual projects should be well structured and handled dynamically here if(cmd == 20001) { LoginResponse.LoginRep loginRep = LoginResponse.LoginRep.parseFrom(bytes); System.out.println("Server returns data:" + loginRep); } //Closed Current out.close(); System.out.println("client close"); } }
The process of parsing the service-side code is to parse it according to the format sent by the front-end.This is the basis of all communication.Specific rules can actually be formulated based on the needs of the project.
/** * protocolbuf3 Server-side processing * @author sodaChen * @date 2019.07.06 */ public class Server { public static void main(String[] args) throws Exception { //Establish Socket Server ServerSocket serverSocket = new ServerSocket(19000); System.out.println("The server socket start-up."); while (true) { //Listen for client connections Socket clientSocket = serverSocket.accept(); System.out.println("There is a client connection up"); // DataInputStream that reads information from clients DataInputStream in = new DataInputStream(clientSocket.getInputStream()); // DataOutputStream that sends information to clients DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream()); //Receive message length size first short msgLength = in.readShort(); //Define the version of the message, currently not available short version = in.readShort(); //Message directive, which is important for identifying what comes next in the message body short cmd = in.readShort(); //The remaining bytes are the message body (minus four bytes of the degree already passed) byte[] bytes = new byte[msgLength - 4]; //Direct reading in.read(bytes); //This directly determines the value of the cmd. If you do a project, the code here will be encapsulated at the bottom and should be parsed automatically, not manually if(cmd == 10001) { //Convert to Logon Request Object LoginRequest.LoginReq loginReq = LoginRequest.LoginReq.parseFrom(bytes); System.out.printf("loginReq:" + loginReq); // LoginResponse.LoginRep.Builder builder = LoginResponse.LoginRep.newBuilder(); if(loginReq.getName().equals("soda")) { builder.setResult(1); builder.setMsg("Login Successful"); } else { builder.setResult(0); builder.setMsg("Logon Failure"); } //Create Login Return Object LoginResponse.LoginRep loginRep = builder.build(); //Encapsulate message body to front end //Calculate Sent pb Protocol Size byte[] bodyBytes = loginRep.toByteArray(); //Define message header (message body content + cmd size), server does not need to return version number out.writeShort(bodyBytes.length + 2); //Message directive, server returns 20001 out.writeShort(20001); //Write message body out.write(bodyBytes); out.flush(); } } } }