您的位置:首页 > 理论基础 > 计算机网络

Tcp投票通信例子

2016-04-14 20:59 459 查看
用到的二进制编码:

import java.io.*;

/* Wire Format
*                                1  1  1  1  1  1
*  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* |     Magic       |Flags|       ZERO            |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* |                  Candidate ID                 |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* |                                               |
* |         Vote Count (only in response)         |
* |                                               |
* |                                               |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/
public class VoteMsgBinCoder implements VoteMsgCoder {

// manifest constants for encoding
public static final int MIN_WIRE_LENGTH = 4;
public static final int MAX_WIRE_LENGTH = 16;
public static final int MAGIC = 0x5400;
public static final int MAGIC_MASK = 0xfc00;
public static final int MAGIC_SHIFT = 8;
public static final int RESPONSE_FLAG = 0x0200;
public static final int INQUIRE_FLAG = 0x0100;

public byte[] toWire(VoteMsg msg) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(byteStream); // converts ints

short magicAndFlags = MAGIC;
if (msg.isInquiry()) {
magicAndFlags |= INQUIRE_FLAG;
}
if (msg.isResponse()) {
magicAndFlags |= RESPONSE_FLAG;
}
out.writeShort(magicAndFlags);
// We know the candidate ID will fit in a short: it's > 0 && < 1000
out.writeShort((short) msg.getCandidateID());
if (msg.isResponse()) {
out.writeLong(msg.getVoteCount());
}
out.flush();
byte[] data = byteStream.toByteArray();
return data;
}

public VoteMsg fromWire(byte[] input) throws IOException {
// sanity checks
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();
if ((magic & MAGIC_MASK) != MAGIC) {
throw new IOException("Bad Magic #: " +
((magic & MAGIC_MASK) >> MAGIC_SHIFT));
}
boolean resp = ((magic & RESPONSE_FLAG) != 0);
boolean inq = ((magic & INQUIRE_FLAG) != 0);
int candidateID = in.readShort();
if (candidateID < 0 || candidateID > 1000) {
throw new IOException("Bad candidate ID: " + candidateID);
}
long count = 0;
if (resp) {
count = in.readLong();
if (count < 0) {
throw new IOException("Bad vote count: " + count);
}
}
// Ignore any extra bytes
return new VoteMsg(resp, inq, candidateID, count);
}
}


一.服务端

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class VoteServerTCP {
public static void main(String args[]) throws Exception {
ServerSocket servSock = new ServerSocket(9000);
//基于二进制的编码协议消息格式
VoteMsgCoder coder = new VoteMsgBinCoder();
VoteService service = new VoteService();
while (true) {
//接受客户端请求(没有客户端请求时是阻塞的)
Socket clntSock = servSock.accept();
System.out.println("Handling client at " + clntSock.getRemoteSocketAddress());
//基于长度的成帧方法
Framer framer = new LengthFramer(clntSock.getInputStream());
try {
byte[] req;
//从输入流中读取下一条信息(底层会调用in.read()方法.此方法是阻塞的,直到输入的数据是可读时.)
while ((req = framer.nextMsg()) != null) {//读到了输入流的末端,就会跳出循环
System.out.println("Received message (" + req.length + " bytes)");
//将信息转换成VoteMsg实例(相当于反序列化)
VoteMsg responseMsg = service.handleRequest(coder.fromWire(req));
//将信息转换成byte字节(相当于序列化),并发送到客户端.
framer.frameMsg(coder.toWire(responseMsg), clntSock.getOutputStream());
}
} catch (IOException ioe) {
System.err.println("Error handling client: " + ioe.getMessage());
} finally {
System.out.println("Closing connection");
//关闭socket
clntSock.close();
}
}
}
}


还有服务端处理查询与投票请求的服务类

import java.util.HashMap;
import java.util.Map;

public class VoteService {

// Map of candidates to number of votes
private Map<Integer, Long> results = new HashMap<Integer, Long>();

public VoteMsg handleRequest(VoteMsg msg) {
if (msg.isResponse()) { // If response, just send it back
return msg;
}
msg.setResponse(true); // Make message a response
// Get candidate ID and vote count
int candidate = msg.getCandidateID();
Long count = results.get(candidate);
if (count == null) {
count = 0L; // Candidate does not exist
}
if (!msg.isInquiry()) {
results.put(candidate, ++count); // If vote, increment count
}
msg.setVoteCount(count);
return msg;
}
}


二.客户端

import java.io.OutputStream;
import java.net.Socket;

public class VoteClientTCP {

public static final int CANDIDATEID = 888;

public static void main(String args[]) throws Exception {

Socket sock = new Socket("127.0.0.1", 9000);
OutputStream out = sock.getOutputStream();

//创建一个二进制编码实例
VoteMsgCoder coder = new VoteMsgBinCoder();
//创建一个基于长度的成帧方法实例
Framer framer = new LengthFramer(sock.getInputStream());

//创建一个查询请求消息
VoteMsg msg = new VoteMsg(false, true, CANDIDATEID, 0);
//将消息转成字节码(相当于序列化))
byte[] encodedMsg = coder.toWire(msg);

System.out.println("Sending Inquiry (" + encodedMsg.length + " bytes): ");
System.out.println(msg);
//发送查询请求
framer.frameMsg(encodedMsg, out);

//改为投票请求
msg.setInquiry(false);
//将消息转成字节码(相当于序列化)
encodedMsg = coder.toWire(msg);
System.out.println("Sending Vote (" + encodedMsg.length + " bytes): ");
//发送投票请求
framer.frameMsg(encodedMsg, out);

//从响应取出查询消息
encodedMsg = framer.nextMsg();
//转为VoteMsg实例(相当于反序列化)
msg = coder.fromWire(encodedMsg);
System.out.println("Received Response (" + encodedMsg.length + " bytes): ");
System.out.println(msg);

//从响应取出投票消息
encodedMsg = framer.nextMsg();
msg = coder.fromWire(encodedMsg);
System.out.println("Received Response (" + encodedMsg.length + " bytes): ");
System.out.println(msg);
//关闭socket
sock.close();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  tcp 通信