Java TCP/IP socket programming Reading Notes (8)

Source: Internet
Author: User
Tags return tag votebuilder
3.5 build and parse message protocols

The following is a simple example.

The program supports two types of requests. One is the query (Inquiry), that is, to ask the server about the total number of votes currently received by a given candidate. The server sends a response message that contains the original candidate ID and the total number of votes received by the current candidate (when the query request is received. Another is a voting request, that is, a vote for a specified candidate. The server also sends a response message to this request, including the candidate ID and the number of votes it receives (including the one vote just made ).

The following is the entity class of the voting information, including whether to query the message, whether to return the message, the candidate number, and the total number of votes.

Package COM. suifeng. tcpip. chapter3.vote;/*** voting message entity ** @ author suifeng **/public class votemsg {private Boolean isinquery; // whether to query the message private Boolean isresponse; // whether the returned message is private int candidate; // candidate number private long votecount; // total number of votes Private Static final int max_candidate_id = 1000; Public votemsg (Boolean isinquery, Boolean isresponse, int candidate, long votecount) {If ((! Isresponse) & votecount> 0) {Throw new illegalargumentexception ("request vote count must be zero");} If (Candidate <0 | candidate> max_candidate_id) {Throw new illegalargumentexception ("bad candidate ID:" + candidate);} If (votecount <0) {Throw new illegalargumentexception ("Total Count must be greanter than zero ");} this. isinquery = isinquery; this. isresponse = isresponse; this. candidate = candidate; This. votecount = votecount;} public Boolean isinquery () {return isinquery;} public void setinquery (Boolean isinquery) {This. isinquery = isinquery;} public Boolean isresponse () {return isresponse;} public void setresponse (Boolean isresponse) {This. isresponse = isresponse;} public int getcandidate () {return candidate;} public void setcandidate (INT candidate) {If (Candidate <0 | candidate> max_candidate_id) {T Hrow new illegalargumentexception ("bad candidate ID:" + candidate);} This. candidate = candidate;} public long getvotecount () {return votecount;} public void setvotecount (long votecount) {If (((! Isresponse) & votecount> 0) | votecount <0) {Throw new illegalargumentexception ("bad vote count");} This. votecount = votecount;} @ overridepublic string tostring () {string res = ""; Res = (isinquery? "Inquery": "Vote") + "for cadidate" + candidate; If (isresponse) {res = "response to" + Res + "who now has" + votecount + "Vote (s)" ;}return res ;}}

With the voting message, a certain protocol is required to encode and decode it. Votemsgcoder provides an interface for encoding and decoding voting information.

Package COM. suifeng. tcpip. chapter3.vote; import Java. io. ioexception;/*** message and binary conversion interface * @ author suifeng **/public interface votemsgcoder {/*** converts the voting information to a binary stream (according to the specific protocol, convert a message to a byte sequence) * @ Param MSG voting information * @ return * @ throws ioexception */byte [] towire (votemsg MSG) throws ioexception; /*** convert binary data into messages (parse the byte sequence based on the same protocol and construct a message-class instance based on the message content) * @ Param input * @ throws ioexception */votemsg fromwire (byte [] input) throws ioexception ;}

3.5.1 text-based representation

First, we will introduce a version that uses text encoding to encode messages. This protocol uses the UTF-8 character set to encode the text. A message starts with a so-called "magic string", that is, a character sequence, which is used by the recipient to quickly distinguish the message of the voting protocol from the random arrival of spam messages in the network. The Boolean value of the vote/query is encoded as a character. 'V' indicates the voting message, and 'I' indicates the query message. The status of the message, that is, whether it is a server response, indicated by the character 'R. The status mark is followed by the candidate ID, followed by the total number of votes, which are encoded into a decimal string. The votemsgtextcoder class provides a text-based votemsg encoding method.

Package COM. suifeng. tcpip. chapter3.vote; import Java. io. bytearrayinputstream; import Java. io. ioexception; import Java. io. inputstreamreader; import Java. util. authorization;/*** use text encoding and decoding of voting information */public class votemsgtextcoder implements votemsgcoder {/*** magic string, used to exclude redundant information */public static final string magic = "voting";/*** vote mark */public static final string votestr = "v "; /*** query tag */public static final string INQ STR = "I";/*** return flag */public static final string responsestr = "R "; /*** encoding method */public static final string charsetname = "UTF-8";/*** separator */public static final string delimstr = ""; /*** maximum number of encoded bytes */public static final int max_wire_length = 200; @ overridepublic votemsg fromwire (byte [] input) throws ioexception {bytearrayinputstream in = new bytearrayinputstream (input ); scanner S = new partition (New in Putstreamreader (in, charsetname); string token = ""; Boolean isinquery = false; Boolean isresponse = false; int candidate = 0; long votecount = 0; token = S. next (); // parse whether it is a valid magic string to prevent redundant information if (! Magic. equals (token) {Throw new ioexception ("Bad magic string:" + token);} // record query tag token = S. next (); If (inqstr. equals (token) {isinquery = true;} else if (votestr. equals (token) {isinquery = false;} else {Throw new ioexception ("bad vote/INQ indicator:" + token);} // the token = s returned. next (); If (responsestr. equals (token) {isresponse = true; // go to the next field -- candidate ID token = S. next ();} else {// non-returned information, which is the candidate ID isresponse = false;} c Andidate = integer. parseint (token); If (isresponse) {token = S. next (); // read the total number of votes votecount = long. parselong (token);} else {votecount = 0;} return New votemsg (isinquery, isresponse, candidate, votecount);} @ overridepublic byte [] towire (votemsg MSG) throws ioexception {stringbuilder votebuilder = new stringbuilder (256); // magic string votebuilder. append (MAGIC ). append (delimstr); // query/vote mark votebuilder. append (MSG. isinquery ())? Inqstr: votestr ). append (delimstr); If (MSG. isresponse () {// return tag votebuilder. append (responsestr ). append (delimstr);} // The candidate number votebuilder. append (MSG. getcandidate ()). append (delimstr); // total number of votes votebuilder. append (MSG. getvotecount ()). append (delimstr); Return votebuilder. tostring (). getbytes (charsetname );}}

3.5.2 binary representation

The following shows another method to encode the voting protocol message. Unlike text-based messages, the binary format uses messages of a fixed size. Each message starts from a special byte. the maximum value of the byte is 010101. This small amount of redundant information provides a certain degree of assurance for the recipient to receive the appropriate voting message. The minimum two digits of this byte are encoded for two boolean values. The second byte of the message is always 0, and the third and fourth bytes contain the candidateid value. Only the last 8 bytes of the Response Message contain the total number of votes.

Package COM. suifeng. tcpip. chapter3.vote; import Java. io. bytearrayinputstream; import Java. io. bytearrayoutputstream; import Java. io. datainputstream; import Java. io. dataoutputstream; import Java. io. ioexception; /*** use binary encoding and decoding of voting information * ============================ ========================= * 0 1 2 3 4 6 7 8 9 10 11 12 13 14 15 * + -- + * | magic | flags | zero | * + -- + -- + * | Candidate | * + -- + -- + * | vote count (only inresponse) | * + -- + **/public class votemsgbinarycoder implements votemsgcoder {/*** minimum number of bytes */public static final int min_wire_length = 4; /*** maximum number of bytes (including the total number of 4 bytes) */public static final int max_wire_length = 8;/*** magic number 010101 00 0000 0000 */public static final int magic = 0x5400; /*** magic digital mask value 111111 00 0000 0000 */public static final int magic_mask = 0xfc00; /*** get the offset bytes of the magic number */public static final int magic_shift = 8; /*** the returned tag mask value is 0000 0010 0000 0000 */public static final int response_flag = 0x0200; /*** query tag mask value 0000 0001 0000 0000 0100 */public static final int inquery_flag = 0 x; @ overridepublic Vo Temsg fromwire (byte [] input) throws ioexception {system. out. println ("input. length = "+ input. length); If (input. length <min_wire_length) {Throw new ioexception ("runt message !!! ");} Bytearrayinputstream BS = new bytearrayinputstream (input); datainputstream in = new datainputstream (BS); int magic = in. readshort (); // verify whether the mask value is valid to prevent redundant data from appearing if (magic & magic_mask )! = Magic) {Throw new ioexception ("Bad magic #:" + (magic & magic_mask)> magic_shift ));} // get the returned flag Boolean isresponse = (magic & response_flag )! = 0; // obtain the query flag Boolean isinquery = (magic & inquery_flag )! = 0; // obtain the candidate number (2 bytes) int candidate = in. readshort (); If (Candidate <0 | candidate> 1000) {Throw new ioexception ("bad candidate ID:" + candidate);} Long Count = 0; If (isresponse) {// obtain the total number of votes (4 bytes) Count = in. readlong (); If (count <0) {Throw new ioexception ("bad vote count:" + count) ;}return new votemsg (isinquery, isresponse, candidate, count) ;}@ overridepublic byte [] towire (votemsg MSG) throws ioexception {bytes bytestream = new bytearrayoutputstream (); dataoutputstream out = new dataoutputstream (bytestream); short magicandflags = magic; // query flag if (MSG. isinquery () {magicandflags | = inquery_flag;} // returns the flag if (MSG. isresponse () {magicandflags | = response_flag;} // records the first two bytes (6-digit magic number + 1-digit return tag + 1-digit query tag + 8-digit 0) out. writeshort (magicandflags); // record the candidate tag (two-byte, 16-bit) out. writeshort (short) MSG. getcandidate (); If (MSG. isresponse () {// total number (8 bytes, 64-bit) out. writelong (MSG. getvotecount ();} Out. flush (); byte [] msgbytes = bytestream. tobytearray (); system. out. println ("encode MSG byte length =" + msgbytes. length); Return bytestream. tobytearray ();}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.