标签:des style blog http io color ar os 使用
小记:昨天咱们已经了解了Socket的通信原理,可是点对点的一次通信并不是我们想要的,那么今天那我们就继续学习异步通信,简单来说就是服务器端和客户端可以进行多次 互发信息的通信而不用担心通道会关闭。在介绍异步通信时,客户端和服务器端的连接和上面介绍的同步通信建立连接的方式是一样的,只是接收和发送数据的方式改变了!
同步:我叫你吃饭,你若暂时有事情我就一直在那等,不干别的事情,直到你忙完。
异步:我叫你吃饭,你若暂时有事情,我就先撤,干点别的,你忙完了再通过某种方式,如电话,通知我。
异步通信的好处我理解的就是可以多次使用一个Socket增加网络的吞吐量,提高资源的利用率。
下面开始代码分析,和上篇的没多大差别,就是发送和接收数据的方式变了:
服务器端:TcpServer.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Net; 7 using System.Net.Sockets; 8 using System.Threading; 9 10 11 namespace TcpServer 12 { 13 class Program 14 { 15 public static Socket serverSocket; 16 public static Thread thread; 17 18 static void Main(string[] args) 19 { 20 //确定端口号 21 int port = 6000; 22 23 //设定连接IP 24 string host = "127.0.0.1"; 25 26 //将IP地址字符串转化为IP地址实例 27 IPAddress ip = IPAddress.Parse(host); 28 29 //将网络端点表示为 IP 地址和端口号 30 IPEndPoint ipe = new IPEndPoint(ip, port); 31 32 //建立Socket 33 //addressFamily 参数一指定 Socket 类使用的寻址方案 34 //socketType 参数二指定 Socket 类的类型 35 //protocolType 参数三指定 Socket 使用的协议。 36 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 37 38 39 //socket与本地终结点建立关联 40 socket.Bind(ipe); 41 string strSend = "HelloClient"; 42 //开始监听端口 43 socket.Listen(10); 44 Console.WriteLine("服务端已开启,等待客户端连接.....\t" + DateTime.Now.ToString() + DateTime.Now.Millisecond.ToString()); 45 46 //为新建的连接建立新的Socket目的为客户端将要建立连接 47 serverSocket = socket.Accept(); 48 Console.WriteLine("连接已建立......\t\t" + DateTime.Now.ToString() + DateTime.Now.Millisecond.ToString()); 49 Console.WriteLine("客户端->服务端:\t" + serverSocket.RemoteEndPoint + "->" + serverSocket.LocalEndPoint); 50 51 //while (true) 52 { 53 string recStr =string.Empty; 54 //定义缓冲区用于接收客户端的数据 55 byte[] recbyte = new byte[1024]; 56 57 //开始接收数据 58 ReceiveData(); 59 60 //服务端给客户端回送消息 61 strSend = "HelloClient"; 62 63 //服务端发送数据 64 //strSend = Console.ReadLine(); 65 Send(strSend); 66 67 //开启线程监视客户端是否断开 68 thread = new Thread(ClientConnectOrNot); 69 Thread.Sleep(0); 70 thread.Start(); 71 72 73 //serverSocket.Close(); 74 Console.ReadLine(); 75 } 76 } 77 78 /// <summary> 79 /// 监视客户端是否断开 80 /// </summary> 81 public static void ClientConnectOrNot() 82 { 83 //Console.WriteLine(serverSocket.Poll(-1, SelectMode.SelectRead)); 84 if (serverSocket.Poll(-1, SelectMode.SelectRead) == true)//客户端断开 85 { 86 Console.WriteLine(serverSocket.RemoteEndPoint + "断开了连接"); 87 thread.Abort(); 88 89 } 90 else 91 { 92 Console.WriteLine(thread.ThreadState); 93 } 94 } 95 #region 96 /// <summary> 97 /// 异步连接 98 /// </summary> 99 /// <param name="ip"></param> 100 /// <param name="port"></param> 101 /// <param name="clientSocket"></param> 102 public static void Connect(IPAddress ip, int port) 103 { 104 serverSocket.BeginConnect(ip, port, new AsyncCallback(ConnectCallback), serverSocket); 105 } 106 107 private static void ConnectCallback(IAsyncResult ar) 108 { 109 try 110 { 111 Socket handler = (Socket)ar.AsyncState; 112 handler.EndConnect(ar); 113 } 114 catch (SocketException ex) 115 { 116 throw ex; 117 } 118 } 119 /// <summary> 120 /// 发送数据 121 /// </summary> 122 /// <param name="data"></param> 123 public static void Send(string data) 124 { 125 //Send(System.Text.Encoding.UTF8.GetBytes(data)); 126 //解决中文乱码 127 Send(UTF8Encoding.UTF8.GetBytes(data)); 128 129 //byte[] byteData = UTF8Encoding.UTF8.GetBytes(data); 130 //Send(Encoding.ASCII.GetBytes(data)); 131 } 132 /// <summary> 133 /// 发送数据 134 /// </summary> 135 /// <param name="byteData"></param> 136 private static void Send(byte[] byteData) 137 { 138 try 139 { 140 int length = byteData.Length; 141 //byte[] head = BitConverter.GetBytes(length); //这个为什么不对,我也不清楚 142 byte[] head = Encoding.ASCII.GetBytes(length.ToString()); //将发送数据的字节长度写到报头中 143 //head.Length = 4; //开始我想指定头部4个字节长度用来存放字节的总数便于拆包 144 byte[] data = new byte[head.Length + byteData.Length]; //发送包的总大小 145 for (int i = 0; i < 3; i++) 146 { 147 data[i] = 0; 148 } 149 Array.Copy(head, data, head.Length); //将head复制到data中 150 Array.Copy(byteData, 0, data, head.Length, byteData.Length); //将byteData复制到data中 151 152 serverSocket.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), serverSocket); 153 } 154 catch (SocketException ex) 155 { 156 throw ex; 157 } 158 } 159 160 private static void SendCallback(IAsyncResult ar) 161 { 162 try 163 { 164 Socket handler = (Socket)ar.AsyncState; 165 handler.EndSend(ar); 166 } 167 catch (SocketException ex) 168 { 169 throw ex; 170 } 171 } 172 173 /// <summary> 174 /// 接收数据8个字节 175 /// </summary> 176 static byte[] MsgBuffer = new byte[8]; 177 178 /// <summary> 179 /// 接收消息 180 /// </summary> 181 public static void ReceiveData() 182 { 183 serverSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 184 } 185 186 /// <summary> 187 /// 回调接收数据 188 /// </summary> 189 /// <param name="ar"></param> 190 private static void ReceiveCallback(IAsyncResult ar) 191 { 192 try 193 { 194 int REnd = serverSocket.EndReceive(ar); 195 if (REnd > 0) 196 { 197 byte[] data = new byte[REnd]; 198 Array.Copy(MsgBuffer, 0, data, 0, REnd); 199 int Msglen = data.Length; 200 //在此次可以对data进行按需处理 201 serverSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 202 Console.WriteLine("来自到客户端{0}字节:{1} \tTime:{2}",REnd ,UTF8Encoding .UTF8.GetString(data, 0, Msglen),DateTime.Now.ToString()+ DateTime.Now.Millisecond.ToString()); 203 } 204 else 205 { 206 dispose(); 207 } 208 } 209 catch (SocketException ex) 210 { 211 throw ex; 212 } 213 } 214 215 /// <summary> 216 /// 释放连接 217 /// </summary> 218 private static void dispose() 219 { 220 try 221 { 222 serverSocket.Shutdown(SocketShutdown.Both); 223 serverSocket.Close(); 224 } 225 catch (Exception ex) 226 { 227 throw ex; 228 } 229 } 230 #endregion 231 } 232 }
客户端 TcpClient.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Net; 7 using System.Net.Sockets; 8 using System.Threading; 9 10 namespace TcpClient 11 { 12 class Program 13 { 14 static int port = 6000; //监听端口号 15 static string host = "127.0.0.1"; //连接服务端IP 16 static IPAddress ip = IPAddress.Parse(host); //将IP地址转换为IP实例 17 static IPEndPoint ipe = new IPEndPoint(ip, port);//将网络端点表示为 IP 地址和端口号 18 static Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//建立客户端Socket 19 20 static Thread thread_client; 21 static void Main(string[] args) 22 { 23 Connect(ip, port);//异步连接 24 string sendStr = "Nice to meet you,Server!"; 25 thread_client = new Thread(ClientConnectOrNot); 26 Thread.Sleep(0); 27 thread_client.Start(); 28 { 29 Console.WriteLine("服务器->客户端:" + clientSocket.RemoteEndPoint + "->" + clientSocket.LocalEndPoint); 30 Send(sendStr); //发送消息 31 ReceiveData(); //接收消息 32 sendStr = Console.ReadLine(); 33 } 34 35 } 36 /// <summary> 37 /// 判断服务端是否关闭 38 /// </summary> 39 public static void ClientConnectOrNot() 40 { 41 if (clientSocket.Poll(-1, SelectMode.SelectRead) == true) //检测服务端是否关闭 42 { 43 Console.WriteLine(clientSocket.RemoteEndPoint+"服务端已关闭..."); 44 45 //thread_client.Abort(); 46 //Thread exit = new Thread(ApplicationExit); //自动关闭程序 47 //Thread.Sleep(3000); 48 //exit.Start(); 49 50 } 51 else 52 { 53 Console.WriteLine(thread_client.ThreadState); 54 } 55 } 56 /// <summary> 57 /// 退出程序关闭Dos窗口 58 /// </summary> 59 public static void ApplicationExit() 60 { 61 Environment.Exit(0); 62 } 63 64 #region 65 /// <summary> 66 /// 异步连接 67 /// </summary> 68 /// <param name="ip"></param> 69 /// <param name="port"></param> 70 /// <param name="clientSocket"></param> 71 public static void Connect(IPAddress ip, int port) 72 { 73 clientSocket.BeginConnect(ip, port, new AsyncCallback(ConnectCallback), clientSocket); 74 } 75 76 private static void ConnectCallback(IAsyncResult ar) 77 { 78 try 79 { 80 Socket handler = (Socket)ar.AsyncState; 81 handler.EndConnect(ar); 82 } 83 catch (SocketException ex) 84 { 85 throw ex; 86 } 87 } 88 /// <summary> 89 /// 发送数据 90 /// </summary> 91 /// <param name="data"></param> 92 public static void Send(string data) 93 { 94 //Send(System.Text.Encoding.UTF8.GetBytes(data)); 95 //Send(Encoding.ASCII.GetBytes(data)); 96 Send(UTF8Encoding.UTF8.GetBytes(data)); 97 } 98 /// <summary> 99 /// 发送数据 100 /// </summary> 101 /// <param name="byteData"></param> 102 private static void Send(byte[] byteData) 103 { 104 try 105 { 106 int length = byteData.Length; 107 //byte[] head = BitConverter.GetBytes(length); 108 byte[] head = Encoding.ASCII.GetBytes(length.ToString()); //头部表示字节的总长度 109 byte[] data = new byte[head.Length + byteData.Length]; 110 Array.Copy(head, data, head.Length); 111 Array.Copy(byteData, 0, data, head.Length, byteData.Length); 112 clientSocket.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), clientSocket); 113 } 114 catch (SocketException ex) 115 { } 116 } 117 /// <summary> 118 /// 回调发送 119 /// </summary> 120 /// <param name="ar"></param> 121 private static void SendCallback(IAsyncResult ar) 122 { 123 try 124 { 125 Socket handler = (Socket)ar.AsyncState; 126 handler.EndSend(ar); 127 } 128 catch (SocketException ex) 129 { 130 throw ex; 131 } 132 } 133 134 /// <summary> 135 /// 定义缓冲区接收数据8个字节 136 /// </summary> 137 static byte[] MsgBuffer = new byte[8]; 138 139 /// <summary> 140 /// 接收消息 141 /// </summary> 142 public static void ReceiveData() 143 { 144 clientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 145 } 146 static bool first = true; 147 private static void ReceiveCallback(IAsyncResult ar) 148 { 149 try 150 { 151 int REnd = clientSocket.EndReceive(ar); 152 if (REnd > 0) 153 { 154 byte[] data = new byte[REnd]; 155 Array.Copy(MsgBuffer, 0, data, 0, REnd); 156 157 int Msglen = data.Length; 158 //在此次可以对data进行按需处理 159 160 clientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 161 string revStr = UTF8Encoding .UTF8.GetString(data, 0, Msglen); 162 if (first) 163 { 164 string len = revStr.Substring(0, 2); 165 first = false; 166 } 167 Console.WriteLine("来自服务端{0}字节:{1}\tTime:{2}",REnd,revStr,DateTime.Now.ToString()+ DateTime.Now.Millisecond.ToString()); 168 } 169 else 170 { 171 dispose(); 172 } 173 } 174 catch (SocketException ex) 175 { } 176 } 177 /// <summary> 178 /// 释放Socket 179 /// </summary> 180 private static void dispose() 181 { 182 try 183 { 184 clientSocket.Shutdown(SocketShutdown.Both); 185 clientSocket.Close(); 186 } 187 catch (Exception ex) 188 { 189 throw ex; 190 } 191 } 192 #endregion 193 } 194 }
先打开服务端:
标签:des style blog http io color ar os 使用
原文地址:http://www.cnblogs.com/wuzhang/p/wuzhang20141117.html