socket通信的套路,无论是同步的方式或者异步的实现方式,套路总是不变的,,那就是服务端开启一个线程监听客户端socket,客户端创建一个socket去连接服务端的监听端口,服务端接收这个客户端socket,在开辟一个线程负责与客户端线程通信(send receive 数据),这里有个误区,并不是监听socket与客户端socket进行通信,监听socket只是负责接收客户端连接请求,最后接收到的socket与客户端socket进行通信。
关于同步和异步的主要区别在哪里?
Accept Receive是阻塞的方法,通常线程在执行到这里的时候就阻塞了。那么他们之后的代码是无法执行的,Accept Receive的异步方法允许你执行他们之后的处理。举个简单的例子,假如客户端正在Receive一段数据,数据比较长,需要10秒,那么Receive之后的代码我们想立刻执行,不需要等待接收完毕才执行,这时候异步Receive就起到作用了,但是这里面依旧有个误区,异步会不会起到增大并发处理效果?并不会,异步只是起到不阻塞线程的作用(异步本身也是开辟一个新的线程去等待接收数据完毕进行处理),并不会起到增大并发接收数据的能力。并发处理归根结底还是由线程来控制的,就算是同步的处理方式,我们开辟多个线程针对对同一个socket进行Receive操作,依旧可以起到并发的效果。
private void ConnectToServer() {//创建一个套接字 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001); clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //将套接字与远程服务器地址相连 try { //客户端连接 clientSocket.Connect(ipep); } catch (SocketException ex) { MessageBox.Show("connect error: " + ex.Message); return; } for (int i = 0; i <= 3;i++ ) { Thread th = new Thread(new ThreadStart(Receive)); th.IsBackground = true; th.Start(); } } public void Receive() { byte[] data = new byte[1024]; while (true) { //接收服务器信息 int bufLen = 0; try { if (clientSocket.Connected) { bufLen = clientSocket.Receive(data); if (bufLen == 0) {break; } } } catch (Exception ex) { MessageBox.Show("Receive Error:" + ex.Message); return; } string clientcommand = System.Text.Encoding.UTF8.GetString(data, 0, bufLen);//.Substring(0, bufLen); SetTextValue(clientcommand+Thread.CurrentThread.ManagedThreadId.ToString()); } }
以上代码是客户端接收数据的处理过程,开辟了4个线程针对同一个socket做并发接收数据的能力。
接下来看看异步接收数据的实现方式
private void ConnectToServer() { byte[] data = new byte[1024]; //创建一个套接字 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001); clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //将套接字与远程服务器地址相连 try { //客户端连接 clientSocket.Connect(ipep); } catch (SocketException ex) { MessageBox.Show("connect error: " + ex.Message); return; } if (clientSocket.Connected) { clientSocket.BeginReceive(buffer, 0, data.Length, SocketFlags.None, Receive, clientSocket); } } static byte[] buffer = new byte[1024]; public void Receive(IAsyncResult ar) { try { var socket = ar.AsyncState as Socket; var bufLen = socket.EndReceive(ar); if (bufLen > 0) { string clientcommand = System.Text.Encoding.UTF8.GetString(buffer, 0, bufLen);//.Substring(0, bufLen); SetTextValue(clientcommand + Thread.CurrentThread.ManagedThreadId.ToString()); socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Receive), socket); } if (bufLen == 0) { SetTextValue("socket shutdown"); } } catch (Exception ex) { MessageBox.Show("Receive Error:" + ex.Message); } }
经过测试,异步接收数据的线程始终是同一个线程,所以异步本身没有起到并发处理的能力,除非开辟多个线程进行异步接收数据。
如何实现这样的一种场景?