投票协议:二进制表示方法
二进制表示方法
下面我们将展示另一种对投票协议消息进行编码的方法。与基于文本的格式相反,二进制格式使用固定大小的消息。每条消息由一个特殊字节开始,该字节的最高六位为一个"魔术"值010101。这一点少量的冗余信息为接收者收到适当的投票消息提供了一定程度的保证。该字节的最低两位对两个布尔值进行了编码。消息的第二个字节总是0,第三、第四个字节包含了candidateID值。只有响应消息的最后8个字节才包含了选票总数信息。
VoteMsgBinCoder.jav
0 import java.io.ByteArrayInputStream;
1 import java.io.ByteArrayOutputStream;
2 import java.io.DataInputStream;
3 import java.io.DataOutputStream;
4 import java.io.IOException;
5
6 /* Wire Format
7 * 1 1 1 1 1 1
8 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
9 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
10 * | Magic |Flags| ZERO |
11 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
12 * | Candidate ID |
13 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
14 * | |
15 * | Vote Count (only in response) |
16 * | |
17 * | |
18 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
19 */
20 public class VoteMsgBinCoder implements VoteMsgCoder {
21
22 // manifest constants for encoding
23 public static final int MIN_WIRE_LENGTH = 4;
24 public static final int MAX_WIRE_LENGTH = 16;
25 public static final int MAGIC = 0x5400;
26 public static final int MAGIC_MASK = 0xfc00;
27 public static final int MAGIC_SHIFT = 8;
28 public static final int RESPONSE_FLAG = 0x0200;
29 public static final int INQUIRE_FLAG = 0x0100;
30
31 public byte[] toWire(VoteMsg msg) throws IOException {
32 ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
33 DataOutputStream out = new DataOutputStream(byteStream); // converts ints
34
35 short magicAndFlags = MAGIC;
36 if (msg.isInquiry()) {
37 magicAndFlags |= INQUIRE_FLAG;
38 }
39 if (msg.isResponse()) {
40 magicAndFlags |= RESPONSE_FLAG;
41 }
42 out.writeShort(magicAndFlags);
43 // We know the candidate ID will fit in a short: it's > 0 && < 1000
44 out.writeShort((short) msg.getCandidateID());
45 if (msg.isResponse()) {
46 out.writeLong(msg.getVoteCount());
47 }
48 out.flush();
49 byte[] data = byteStream.toByteArray();
50 return data;
51 }
52
53 public VoteMsg fromWire(byte[] input) throws IOException {
54 // sanity checks
55 if (input.length < MIN_WIRE_LENGTH) {
56 throw new IOException("Runt message");
57 }
58 ByteArrayInputStream bs = new ByteArrayInputStream(input);
59 DataInputStream in = new DataInputStream(bs);
60 int magic = in.readShort();
61 if ((magic & MAGIC_MASK) != MAGIC) {
62 throw new IOException("Bad Magic #: " +
63 ((magic & MAGIC_MASK) >> MAGIC_SHIFT));
64 }
65 boolean resp = ((magic & RESPONSE_FLAG) != 0);
66 boolean inq = ((magic & INQUIRE_FLAG) != 0);
67 int candidateID = in.readShort();
68 if (candidateID < 0 || candidateID > 1000) {
69 throw new IOException("Bad candidate ID: " + candidateID);
70 }
71 long count = 0;
72 if (resp) {
73 count = in.readLong();
74 if (count < 0) {
75 throw new IOException("Bad vote count: " + count);
76 }
77 }
78 // Ignore any extra bytes
79 return new VoteMsg(resp, inq, candidateID, count);
80 }
81 }
VoteMsgBinCoder.jav
就像在第3.1.1节中一样,我们创建了一个ByteArrayOutputStream并将其包裹在一个DataOutputStream中来接收结果。这个编码方法利用了在合法candidateID中,其最高两个字节始终为0的特点。还要注意的是,该方法通过使用按位或操作,使用1位对每个布尔值进行编码。
相关下载:
Java_TCPIP_Socket编程(doc)
http://download.csdn.net/detail/undoner/4940239
文献来源:
UNDONER(小杰博客) :http://blog.csdn.net/undoner
LSOFT.CN(琅软中国) :http://www.lsoft.cn