基于C#的socket编程的TCP异步的实现代码

2019-12-30 14:24:36刘景俊

接收数据是通过BeginReceive和EndReceive方法:


private static void Receive(Socket client)
{
 try
 {
  // Create the state object.  
  StateObject state = new StateObject();
  state.workSocket = client;
  // Begin receiving the data from the remote device.  
  client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
 }
 catch (Exception e)
 {
  Console.WriteLine(e.ToString());
 }
}
private static void ReceiveCallback(IAsyncResult ar)
{
 try
 {
  // Retrieve the state object and the client socket  
  // from the asynchronous state object.  
  StateObject state = (StateObject)ar.AsyncState;
  Socket client = state.workSocket;
  // Read data from the remote device.  
  int bytesRead = client.EndReceive(ar);
  if (bytesRead > 0)
  {
   // There might be more data, so store the data received so far.  

   state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
   // Get the rest of the data.  
   client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
  }
  else
  {
   // All the data has arrived; put it in response.  
   if (state.sb.Length > 1)
   {
    response = state.sb.ToString();
   }
   // Signal that all bytes have been received.  
   receiveDone.Set();
  }
 }
 catch (Exception e)
 {
  Console.WriteLine(e.ToString());
 }
}

上述代码的处理逻辑为:

(1)首先处理连接的回调函数里得到的通讯套接字client,接着开始接收数据;

(2)当数据发送到缓冲区中,BeginReceive方法试图从buffer数组中读取长度为buffer.length的数据块,并返回接收到的数据量bytesRead。最后接收并打印数据。

除了上述方法外,还可以使用基于NetworkStream相关的异步发送和接收方法,下面是基于NetworkStream相关的异步发送和接收方法的使用介绍。

NetworkStream使用BeginRead和EndRead方法进行读操作,使用BeginWreite和EndWrete方法进行写操作,下面看实例:


static void DataHandle(TcpClient client)
{
 TcpClient tcpClient = client;
 //使用TcpClient的GetStream方法获取网络流
 NetworkStream ns = tcpClient.GetStream();
 //检查网络流是否可读
 if(ns.CanRead)
 {
 //定义缓冲区
 byte[] read = new byte[1024];
 ns.BeginRead(read,0,read.Length,new AsyncCallback(myReadCallBack),ns); 
 }
 else
 {
 Console.WriteLine("无法从网络中读取流数据");
 }
}

public static void myReadCallBack(IAsyncResult iar)
{
 NetworkStream ns = (NetworkStream)iar.AsyncState;
 byte[] read = new byte[1024];
 String data = "";
 int recv;

 recv = ns.EndRead(iar);
 data = String.Concat(data, Encoding.ASCII.GetString(read, 0, recv));

 //接收到的消息长度可能大于缓冲区总大小,反复循环直到读完为止
 while (ns.DataAvailable)
 {
  ns.BeginRead(read, 0, read.Length, new AsyncCallback(myReadCallBack), ns);
 }
 //打印
 Console.WriteLine("您收到的信息是" + data);
}