[转载]用TCP/IP实现自己简单的应用程序协议:其余部分 – 浪雪 – 博客园.
接着上次用TCP/IP实现自己简单的应用程序协议:成帧器部分,现在把接下来的部分也说完
代码下载:
http://download.csdn.net/source/3519903
客户端的调用:
public class VoteClientTCP { public static int CANDIDATEID = 888;//随便写了一个 public static void Main(String[] args) { int port = 5555; IPEndPoint ipep = new IPEndPoint(GetLocalhostIPv4Addresses().First(), port); Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { sock.Connect(ipep); } catch (SocketException e) { Console.WriteLine("Can not connect {0} ,reason:{1},NativeErrorCode:{2},SocketErrorCode:{3}", ipep.Address, e.Message, e.NativeErrorCode, e.SocketErrorCode); Console.ReadKey(); return; } IVoteMsgCoder coder = new VoteMsgTextCoder(); IFramer framer = new LengthFramer(sock); VoteMsg msg = new VoteMsg(true, false, CANDIDATEID, 1); byte[] encodedMsg = coder.toWire(msg); // 发送查询 Console.WriteLine("Sending Inquiry (" + encodedMsg.Length + " bytes): "); framer.frameMsg(encodedMsg); // 投第一票给候选人888 msg.IsInquiry = false; encodedMsg = coder.toWire(msg); Console.WriteLine("Sending Vote (" + encodedMsg.Length + " bytes): "); framer.frameMsg(encodedMsg); // 投第二票给候选人888 msg.IsInquiry = false; encodedMsg = coder.toWire(msg); Console.WriteLine("Sending Vote (" + encodedMsg.Length + " bytes): "); framer.frameMsg(encodedMsg); // 再次查询 msg.IsInquiry = true; encodedMsg = coder.toWire(msg); Console.WriteLine("Sending Inquiry (" + encodedMsg.Length + " bytes): "); framer.frameMsg(encodedMsg); encodedMsg = framer.nextMsg(); msg = coder.fromWire(encodedMsg); Console.WriteLine("Received Response (" + encodedMsg.Length + " bytes): "); Console.WriteLine(msg); msg = coder.fromWire(framer.nextMsg()); Console.WriteLine("Received Response (" + encodedMsg.Length + " bytes): "); Console.WriteLine(msg); msg = coder.fromWire(framer.nextMsg()); Console.WriteLine("Received Response (" + encodedMsg.Length + " bytes): "); Console.WriteLine(msg); msg = coder.fromWire(framer.nextMsg()); Console.WriteLine("Received Response (" + encodedMsg.Length + " bytes): "); Console.WriteLine(msg); sock.Shutdown(SocketShutdown.Both); sock.Close(); Console.ReadLine(); } //辅助方法 public static IPAddress[] GetLocalhostIPv4Addresses() { IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName()); List<IPAddress> list = new List<IPAddress>(); foreach (IPAddress address in hostEntry.AddressList) { if (address.AddressFamily == AddressFamily.InterNetwork) { list.Add(address); } } return list.ToArray(); } }
服务端接收并返回数据:
public class VoteServerTCP { public static void Main(String[] args){ int port = 5555; Socket servSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );; //编码对象 IVoteMsgCoder coder = new VoteMsgTextCoder(); //服务对象 VoteService service = new VoteService(); //创建IP终结点 IPAddress localAddress = AddressHelper.GetLocalhostIPv4Addresses().First(); IPEndPoint ipep = new IPEndPoint(localAddress, port); servSock.Bind(ipep); servSock.Listen(1); while (true) { Socket clntSock = servSock.Accept(); Console.WriteLine("Handling client at " + clntSock.AddressFamily); IFramer framer = new LengthFramer(clntSock); try { byte[] req; while ((req = framer.nextMsg()) != null) { Console.WriteLine("Received message (" + req.Length + " bytes)"); VoteMsg responseMsg = service.handleRequest(coder.fromWire(req)); //发回反馈消息 framer.frameMsg(coder.toWire(responseMsg)); } } catch (SocketException soe) { //比如说客户端提发送多条消息,又在全部接收前关闭socket时就会引发此类异常。 Console.WriteLine("Error handling client: " + soe.Message); } finally { Console.WriteLine("Closing connection"); clntSock.Close(); } } } }
对字符串编码的简单实现
public class VoteMsgTextCoder : IVoteMsgCoder { // 下面是需要进行编码的字段 public static readonly String MAGIC = "Voting"; public static readonly String VOTESTR = "v"; public static readonly String INQSTR = "i"; public static readonly String RESPONSESTR = "R"; public static readonly String DELIMSTR = " "; UTF8Encoding encoder = null; public static readonly int MAX_WIRE_LENGTH = 2000; public VoteMsgTextCoder() { encoder = new UTF8Encoding(); } public byte[] toWire(VoteMsg msg) { String msgString = MAGIC + DELIMSTR + (msg.IsInquiry ? INQSTR : VOTESTR) + DELIMSTR + (msg.IsResponse ? RESPONSESTR + DELIMSTR : "") + msg.CandidateID.ToString() + DELIMSTR + msg.VoteCount.ToString(); byte[] data = encoder.GetBytes(msgString); return data; } public VoteMsg fromWire(byte[] message) { bool isInquiry; bool isResponse; int candidateID; long voteCount; string token; string StringSentByClient = Encoding.UTF8.GetString(message); string[] fields = StringSentByClient.Split(new char[] { ' ' }); try { token = fields[0]; if (!token.Equals(MAGIC)) { throw new IOException("Bad magic string: " + token); } token = fields[1]; if (token.Equals(VOTESTR)) { isInquiry = false; } else if (!token.Equals(INQSTR)) { throw new IOException("Bad vote/inq indicator: " + token); } else { isInquiry = true; } token = fields[2]; if (token.Equals(RESPONSESTR)) { isResponse = true; token = fields[3]; } else { isResponse = false; } candidateID = int.Parse(token); if (isResponse) { token = fields[4]; voteCount = long.Parse(token); } else { voteCount = 0; } } catch (IOException ioe) { throw new IOException("Parse error..."); } return new VoteMsg(isInquiry, isResponse, candidateID, voteCount); } }
运行结果: