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(); } }
相关文章推荐
- C#实现子窗体与父窗体通信方法实例总结
- TCP版backshell的VBS脚本代码
- java和c#使用hessian通信的方法
- win32下进程间通信(共享内存)实例分析
- WinForm实现跨进程通信的方法
- C#中使用UDP通信实例
- ASP.NET UserControl 通信的具体实现
- 使用C语言编写基于TCP协议的Socket通讯程序实例分享
- TCP Wrappers防火墙介绍与封锁IP地址的方法
- c语言多进程tcp服务器示例
- 浅析iOS应用开发中线程间的通信与线程安全问题
- win2003连接限制TCP连接限制
- PHP多线程编程之管道通信实例分析
- flex与js通信与彼此之间的互调整理(一)
- PowerShell脚本开发之收发TCP消息包
- Nodejs创建TCP服务器 - king0222
- Perl的Mail::POP3Client模块和Gmail通信实例
- C#实现TCP连接信息统计的方法
- 使用DNode实现php和nodejs之间通信的简单实例
- 嵌入式iframe子页面与父页面js通信的方法