投票协议:基于文本的表示方法

首先,我们介绍一个用文本方式对消息进行编码的版本。该协议指定使用US-ASCII符集对文本进行编码。消息的开头是一个所谓的"魔术字符串",即一个字符序列,用于接收者快速将投票协议的消息和网络中随机到来的垃圾消息区分开。投票/查询布尔值被编码成字符形式,'v'表示投票消息,'i'表示查询消息。消息的状态,即是否为服务器的响应,由字'R'指示。状态标记后面是候选人ID,其后跟的是选票总数,它们都编码成十进制字符串。

VoteMsgTextCoder类提供了一种基于文本的VoteMsg编码方法。

 VoteMsgTextCoder.java

0 import java.io.ByteArrayInputStream;

1 import java.io.IOException;

2 import java.io.InputStreamReader;

3 import java.util.Scanner;

4

5 public class VoteMsgTextCoder implements VoteMsgCoder

{

6 /*

7 * Wire Format "VOTEPROTO" <"v"|"i"> [<RESPFLAG>]

<CANDIDATE> [<VOTECNT>]

8 * Charset is fixed by the wire format.

9 */

10

11 // Manifest constants for encoding

12 public static final String MAGIC = "Voting";

13 public static final String VOTESTR = "v";

14 public static final String INQSTR = "i";

15 public static final String RESPONSESTR = "R";

16

17 public static final String CHARSETNAME = "US-ASCII";

18 public static final String DELIMSTR = " ";

19 public static final int MAX_WIRE_LENGTH = 2000;

20

21 public byte[] toWire(VoteMsg msg) throws IOException

{

22 String msgString = MAGIC + DELIMSTR + (msg.isInquiry() ?

INQSTR : VOTESTR)

23 + DELIMSTR + (msg.isResponse() ? RESPONSESTR +

DELIMSTR : "")

24 + Integer.toString(msg.getCandidateID()) + DELIMSTR

25 + Long.toString(msg.getVoteCount());

26 byte data[] = msgString.getBytes(CHARSETNAME);

27 return data;

28 }

29

30 public VoteMsg fromWire(byte[] message) throws

IOException {

31 ByteArrayInputStream msgStream = new

ByteArrayInputStream(message);

32 Scanner s = new Scanner(new

InputStreamReader(msgStream, CHARSETNAME));

33 boolean isInquiry;

34 boolean isResponse;

35 int candidateID;

36 long voteCount;

37 String token;

38

39 try {

40 token = s.next();

41 if (!token.equals(MAGIC)) {

42 throw new IOException("Bad magic string: " + token);

43 }

44 token = s.next();

45 if (token.equals(VOTESTR)) {

46 isInquiry = false;

47 } else if (!token.equals(INQSTR)) {

48 throw new IOException("Bad vote/inq indicator: " +

token);

49 } else {

50 isInquiry = true;

51 }

52

53 token = s.next();

54 if (token.equals(RESPONSESTR)) {

55 isResponse = true;

56 token = s.next();

57 } else {

58 isResponse = false;

59 }

60 // Current token is candidateID

61 // Note: isResponse now valid

62 candidateID = Integer.parseInt(token);

63 if (isResponse) {

64 token = s.next();

65 voteCount = Long.parseLong(token);

66 } else {

67 voteCount = 0;

68 }

69 } catch (IOException ioe) {

70 throw new IOException("Parse error...");

71 }

72 return new VoteMsg(isResponse, isInquiry, candidateID,

voteCount);

73 }

74 }

 

VoteMsgTextCoder.java

toWire()方法简单地创建一个字符串,该字符串中包含了消息的所有字段,并由空白符隔开。fromWire()方法首先检查"魔术"字符串,如果在消息最前面没有魔术字符串,则抛出一个异常。这里说明了在实现协议时非常重要的一点:永远不要对从网络来的任何输入进行任何假设。你的程序必须时刻为任何可能的输入做好准备,并能够很好地对其进行处理。在这个例子中,如果接收到的不是期望的消息,fromWire()方法将抛出一个异常,否则,就使Scanner实例,根据空白符一个一个地获取字段。注意,消息的字段数与其是请求消息(由客户端发送)还是响应消息(由服务器发送)有关。如果输入流提前结束或格式错误,fromWire()方法将抛出一个异常。

 

相关下载:

Java_TCPIP_Socket编程(doc)

http://download.csdn.net/detail/undoner/4940239

 

文献来源:

UNDONER(小杰博客) :http://blog.csdn.net/undoner

LSOFT.CN(琅软中国) :http://www.lsoft.cn

 

原文地址:https://www.cnblogs.com/wuyida/p/6301076.html