C# Socket异步通信

本文介绍如何使用 C# 实现基于 Socket 的异步通信,包括创建 Socket、监听连接、接收与发送数据等关键步骤,并提供了一个完整的异步 TCP 服务器示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原贴:http://www.cnblogs.com/kingmoon/archive/2011/04/29/2032452.html


C# Socket异步通信 

                                                                     

TCPServer 

1、使用的通讯通道:socket

2、用到的基本功能:

Bind,

Listen,

BeginAccept

EndAccept

BeginReceive 

EndReceive

3、函数参数说明

 Socket listener = new Socket(AddressFamily.InterNetwork,

            SocketType.Stream, ProtocolType.Tcp);

 新建socket所使用的参数均为系统预定义的量,直接选取使用。

listener.Bind(localEndPoint);

localEndPoint 表示一个定义完整的终端,包括IP和端口信息。

//new IPEndPoint(IPAddress,port)

//IPAdress.Parse("192.168.1.3")

listener.Listen(100);

监听

    listener.BeginAccept(

                    new AsyncCallback(AcceptCallback),

                    listener);

  AsyncCallback(AcceptCallback),一旦连接上后的回调函数为AcceptCallback。当系统调用这个函数时,自动赋予的输入参数为IAsyncResoult类型变量ar。

   listener,连接行为的容器。

Socket handler = listener.EndAccept(ar);

完成连接,返回此时的socket通道。

handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,

            new AsyncCallback(ReadCallback), state);

接收的字节,0,字节长度,0,接收时调用的回调函数,接收行为的容器。

========

容器的结构类型为:

Code

public class StateObject
{
    // Client  socket.
    public Socket workSocket = null;
    // Size of receive buffer.
    public const int BufferSize = 1024;
    // Receive buffer.
    public byte[] buffer = new byte[BufferSize];
    // Received data string.
    public StringBuilder sb = new StringBuilder();
}

容器至少为一个socket类型。

===============

  // Read data from the client socket.

        int bytesRead = handler.EndReceive(ar);

完成一次连接。数据存储在state.buffer里,bytesRead为读取的长度。

handler.BeginSend(byteData, 0, byteData.Length, 0,

            new AsyncCallback(SendCallback), handler);

发送数据byteData,回调函数SendCallback。容器handler

int bytesSent = handler.EndSend(ar);

发送完毕,bytesSent发送字节数。

4 程序结构

主程序:

byte[] bytes = new Byte[1024];
       IPAddress ipAddress = IPAddress.Parse("192.168.1.104");
       IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

        // 生成一个TCP的socket
        Socket listener = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

        listener.Bind(localEndPoint);
        listener.Listen(100);

       while (true)
       {

            // Set the event to nonsignaled state.
            allDone.Reset();

            //开启异步监听socket
            Console.WriteLine("Waiting for a connection");
           listener.BeginAccept(
                     new AsyncCallback(AcceptCallback),
                     listener);

           // 让程序等待,直到连接任务完成。在AcceptCallback里的适当位置放置allDone.Set()语句.
            allDone.WaitOne();
           }

    Console.WriteLine("\nPress ENTER to continue");
    Console.Read();

连接行为回调函数AcceptCallback:

Code

    public static void AcceptCallback(IAsyncResult ar)

    {

        //添加此命令,让主线程继续.

        allDone.Set();

        // 获取客户请求的socket

        Socket listener = (Socket)ar.AsyncState;

        Socket handler = listener.EndAccept(ar);

        // 造一个容器,并用于接收命令.

        StateObject state = new StateObject();

        state.workSocket = handler;

        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,

            new AsyncCallback(ReadCallback), state);

    }

读取行为的回调函数ReadCallback:

Code

    public static void ReadCallback(IAsyncResult ar)

    {

        String content = String.Empty;

        // 从异步state对象中获取state和socket对象.

        StateObject state = (StateObject)ar.AsyncState;

        Socket handler = state.workSocket;

        // 从客户socket读取数据.

        int bytesRead = handler.EndReceive(ar);

        if (bytesRead > 0)

        {

            // 如果接收到数据,则存起来

            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

            // 检查是否有结束标记,如果没有则继续读取

            content = state.sb.ToString();

            if (content.IndexOf("<EOF>") > -1)

            {

                //所有数据读取完毕.

                Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",

                    content.Length, content);

                // 给客户端响应.

                Send(handler, content);

            }

            else

            {

                // 接收未完成,继续接收.

                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,

                new AsyncCallback(ReadCallback), state);

            }

        }

    }

发送消息给客户端:

Code

private static void Send(Socket handler, String data)

    {

        // 消息格式转换.

        byte[] byteData = Encoding.ASCII.GetBytes(data);

        // 开始发送数据给远程目标.

        handler.BeginSend(byteData, 0, byteData.Length, 0,

            new AsyncCallback(SendCallback), handler);

    }

private static void SendCallback(IAsyncResult ar)

    {

    

            // 从state对象获取socket.

            Socket handler = (Socket)ar.AsyncState;

            //完成数据发送

            int bytesSent = handler.EndSend(ar);

            Console.WriteLine("Sent {0} bytes to client.", bytesSent);

            handler.Shutdown(SocketShutdown.Both);

            handler.Close();

    }

在各种行为的回调函数中,所对应的socket都从输入参数的AsyncState属性获得。使用(Socket)或者(StateObject)进行强制转换。BeginReceive函数使用的容器为state,因为它需要存放传送的数据。

而其余接收或发送函数的容器为socket也可。

完整代码

using System;
  using System.Net;
  using System.Net.Sockets;
 using System.Text;
 using System.Threading;
 
 // State object for reading client data asynchronously
 public class StateObject
 {
     // Client  socket.
     public Socket workSocket = null;
     // Size of receive buffer.
     public const int BufferSize = 1024;
     // Receive buffer.
     public byte[] buffer = new byte[BufferSize];
     // Received data string.
     public StringBuilder sb = new StringBuilder();
 }
 
 public class AsynchronousSocketListener
 {
     // Thread signal.
     public static ManualResetEvent allDone = new ManualResetEvent(false);
 
     public AsynchronousSocketListener()
     {
     }
 
     public static void StartListening()
     {
         // Data buffer for incoming data.
         byte[] bytes = new Byte[1024];
 
         // Establish the local endpoint for the socket.
         // The DNS name of the computer
         // running the listener is "host.contoso.com".
         //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
         IPAddress ipAddress = IPAddress.Parse("192.168.1.104");
 
         IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
 
         // Create a TCP/IP socket.
         Socket listener = new Socket(AddressFamily.InterNetwork,
             SocketType.Stream, ProtocolType.Tcp);
 
         // Bind the socket to the local endpoint and listen for incoming connections.
         try
         {
             listener.Bind(localEndPoint);
             listener.Listen(100);
             while (true)
             {
                 // Set the event to nonsignaled state.
                 allDone.Reset();
 
                 // Start an asynchronous socket to listen for connections.
                 Console.WriteLine("Waiting for a connection");
                 listener.BeginAccept(
                     new AsyncCallback(AcceptCallback),
                     listener);
 
                 // Wait until a connection is made before continuing.
                 allDone.WaitOne();
             }
         }
         catch (Exception e)
         {
             Console.WriteLine(e.ToString());
         }
 
         Console.WriteLine("\nPress ENTER to continue");
         Console.Read();
     }
 
     public static void AcceptCallback(IAsyncResult ar)
     {
        // Signal the main thread to continue.
         allDone.Set();
 
         // Get the socket that handles the client request.
         Socket listener = (Socket)ar.AsyncState;
         Socket handler = listener.EndAccept(ar);
  
         // Create the state object.
         StateObject state = new StateObject();
         state.workSocket = handler;
         handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
     }
 
     public static void ReadCallback(IAsyncResult ar)
     {
         String content = String.Empty;
      
         // Retrieve the state object and the handler socket
         // from the asynchronous state object.
         StateObject state = (StateObject)ar.AsyncState;
         Socket handler = state.workSocket;
 
         // Read data from the client socket. 
         int bytesRead = handler.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));
 
             // Check for end-of-file tag. If it is not there, read 
             // more data.
             content = state.sb.ToString();
             if (content.IndexOf("<EOF>") > -1)
             {
                 // All the data has been read from the 
                 // client. Display it on the console.
                 Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",content.Length, content);
 
                 // Echo the data back to the client.
                 Send(handler, content);
             }
             else
             {
                 // Not all data received. Get more.
                 handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
             }
         }
     }
 
     private static void Send(Socket handler, String data)
     {
         // Convert the string data to byte data using ASCII encoding.
         byte[] byteData = Encoding.ASCII.GetBytes(data);
 
         // Begin sending the data to the remote device.
         handler.BeginSend(byteData, 0, byteData.Length, 0,
             new AsyncCallback(SendCallback), handler);
     }
 
  
 
     private static void SendCallback(IAsyncResult ar)
 
     {
         try
         {
             // Retrieve the socket from the state object.
             Socket handler = (Socket)ar.AsyncState;
 
             // Complete sending the data to the remote device.
             int bytesSent = handler.EndSend(ar);
             Console.WriteLine("Sent {0} bytes to client.", bytesSent);
             handler.Shutdown(SocketShutdown.Both);
             handler.Close();
         }
 
         catch (Exception e)
 
         {
             Console.WriteLine(e.ToString());
         }
     }
 
     public static int Main(String[] args)
 
     {
         StartListening();
         return 0;
     }
 
 }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值