TCP通信之异步实现
首先本内容是参考于别人的一篇文章,由于时间久远没找到原作者。今天写本篇文章用于技术记录,便于日后查看。
服务端:
public class TCPServer { static byte[] buffer = new byte[1024]; private static int count = 0; public static Socket socket = null; public static Socket socketClient = null; /// <summary> /// 客服端 /// </summary> public static Socket client = null; /// <summary> /// 启动监听 /// </summary> public static void Start(string ip, string port) { try { #region 启动程序 //①创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字) socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //string ip = OperIni.ReadIni("BJIP", "key", "", Program.MainForm.iniFilePath); //string port = OperIni.ReadIni("BJPORT", "key", "", Program.MainForm.iniFilePath); //②将该socket绑定到主机上面的某个端口 //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx socket.Bind(new IPEndPoint(IPAddress.Parse(ip), Int32.Parse(port))); //③启动监听,并且设置一个最大的队列长度 //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx socket.Listen(10000); //④开始接受客户端连接请求 //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx socket.BeginAccept(new AsyncCallback(ClientAccepted), socket); #endregion } catch (Exception err) { // MessageBox.Show("服务器监听打开失败:" + err.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } } #region 客户端连接成功 /// <summary> /// 客户端连接成功 /// </summary> /// <param name="ar"></param> public static void ClientAccepted(IAsyncResult ar) { #region //设置计数器 count++; // var socket = ar.AsyncState as Socket; //这就是客户端的Socket实例,我们后续可以将其保存起来 client = socket.EndAccept(ar); //客户端IP地址和端口信息 IPEndPoint clientipe = (IPEndPoint)client.RemoteEndPoint; //WriteLine(clientipe + " is connected,total connects " + count, ConsoleColor.Yellow); //接收客户端的消息(这个和在客户端实现的方式是一样的)异步 client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client); //准备接受下一个客户端请求(异步) socket.BeginAccept(new AsyncCallback(ClientAccepted), socket); #endregion } #endregion #region 接收和发送客户端的信息 /// <summary> /// 接收某一个客户端的消息 /// </summary> /// <param name="ar"></param> public static void ReceiveMessage(IAsyncResult ar) { int length = 0; string message = ""; //收到到的消息 socketClient = ar.AsyncState as Socket; //客户端IP地址和端口信息 IPEndPoint clientipe = (IPEndPoint)socketClient.RemoteEndPoint; try { #region //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx length = socketClient.EndReceive(ar); if (length == 0) { throw new Exception("客户端断开"); } //读取出来消息内容 //ASCIIEncoding ASC = new ASCIIEncoding(); //message = ASC.GetString(buffer, 0, length); message = Encoding.Default.GetString(buffer); //输出接收信息 WriteLine(clientipe + " :" + message, ConsoleColor.White); //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息)异步 socketClient.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socketClient); #endregion } catch (Exception ex) { //设置计数器 count--; //断开连接 //WriteLine(clientipe + " is disconnected,total connects " + (count), ConsoleColor.Red); } } /// <summary> /// 发送客户端消息 /// </summary> public static void Send(string send) { try { byte[] reply = Encoding.GetEncoding("GB2312").GetBytes(send); client.Send(reply); } catch (Exception err) { // MessageBox.Show("与主控通信失败!" + err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } #endregion #region 扩展方法 public static void WriteLine(string str, ConsoleColor color) { Console.ForegroundColor = color; Console.WriteLine("[{0}] {1}", DateTime.Now.ToString("MM-dd HH:mm:ss"), str); } /// <summary> /// 校验和 /// </summary> /// <param name="msg"></param> /// <returns></returns> public static byte SumMake(byte[] msg) { byte b = 0; for (int i = 1; i < msg.Length - 2; i++) { b += msg[i]; } return b; } #endregion }
客户端:
class TCPClient { private Socket clientSocket; private byte[] receiveBuff; public TCPClient() { receiveBuff = new byte[1024]; } /// <summary> /// 打开连接 /// </summary> /// <returns></returns> public bool connect(string ip, int port) { try { if (clientSocket == null || clientSocket.Connected == false) { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化套接字 } IPEndPoint remotepoint = new IPEndPoint(IPAddress.Parse(ip), port);//根据ip地址和端口号创建远程终结点 EndPoint end = (EndPoint)remotepoint; clientSocket.BeginConnect(end, new AsyncCallback(ConnectedCallback), clientSocket); //调用回调函数 return true; } catch (Exception ex) { Console.WriteLine("设备连接失败:" + ex.Message); return false; } } private void ConnectedCallback(IAsyncResult ar) { try { Socket client = (Socket)ar.AsyncState; client.EndConnect(ar); clientSocket.BeginReceive(receiveBuff, 0, receiveBuff.Length, 0, new AsyncCallback(ReceiveCallback), clientSocket); Console.WriteLine("设备连接成功:" + client.RemoteEndPoint); } catch (Exception e) { Console.WriteLine("设备连接失败:" + e.Message); } } private void ReceiveCallback(IAsyncResult ar) { try { String content = String.Empty; // Retrieve the state object and the handler socket // from the asynchronous state object. Socket handler = (Socket)ar.AsyncState;//获取句柄 // Read data from the client socket. int bytesRead = handler.EndReceive(ar); IPEndPoint remotepoint = (IPEndPoint)handler.RemoteEndPoint;//获取远程的端口 if (bytesRead > 0) { //处理收到的信息 DealReceive(receiveBuff, bytesRead); //处理完之后清空receive_buff clearReceiveBuff(); clientSocket.BeginReceive(receiveBuff, 0, receiveBuff.Length, 0, new AsyncCallback(ReceiveCallback), handler); } } catch (Exception ex) { Console.WriteLine(ex.Message); clearReceiveBuff(); } } private void SendCallback(IAsyncResult ar) //发送的回调函数 { Socket client = (Socket)ar.AsyncState; int bytesSend = client.EndSend(ar); //完成发送 } private void DealReceive(Byte[] receiveByte, int len) { byte[] temp = new byte[len]; Array.Copy(receiveByte, 0, temp, 0, len); //string strReceive = StringConvert.byteToHexStr(temp); string strReceive = Encoding.Default.GetString(temp); Console.WriteLine(strReceive); } private void clearReceiveBuff() { Array.Clear(receiveBuff, 0, 1024); } public void sendToServer(byte[] byteData) { try { if (clientSocket != null && clientSocket.Connected) { clientSocket.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), clientSocket); } } catch (SocketException ex) { Console.WriteLine("TCP发送失败:" + ex.Message); } } }

浙公网安备 33010602011771号