且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

创建多线程环境中的C#异步套接字客户端

更新时间:2021-09-18 22:49:44

下面是一个非阻挡客户端和服务器与实现了一个简单的回波的一个例子。没有错误检查,并没有什么正确关闭它应该做的。该服务器具有一定的同步code只是为了更容易理解。

Here is an example of a non blocking client and server with a simple echo implemented. There is no error checking and nothing is closed correctly which should be done. The server has some synchronous code just to make it easier to follow.

客户端

public class AsyncClient
{
    private const int Port = 9999;
    private readonly string _clientId;
    private readonly Random _random;

    public AsyncClient(int clientId)
    {
        _clientId = string.Format("Client Id: {0}", clientId);
        _random =  new Random(clientId);
    }

    public void StartClient()
    {
        try
        {
            var workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            var state = new ClientState { WorkSocket = workSocket };
            workSocket.BeginConnect(new IPEndPoint(IPAddress.Loopback, Port), ConnectCallBack, state);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    private void ConnectCallBack(IAsyncResult ar)
    {
        var state = (ClientState) ar.AsyncState;
        state.WorkSocket.EndConnect(ar);
        Send(state);
    }

    private void Receive(ClientState clientState)
    {
        clientState.WorkSocket.BeginReceive(clientState.Buffer, 0, ClientState.BufferSize, 0, ReceiveCallBack, clientState);
    }

    private void ReceiveCallBack(IAsyncResult ar)
    {
        var state = (ClientState) ar.AsyncState;
        Socket client = state.WorkSocket;
        int byteReceived= client.EndReceive(ar);
        if (byteReceived > 0)
        {
            var receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
            Console.WriteLine("From Server: " + receivedString);
            Array.Clear(state.Buffer, 0, state.Buffer.Length);
            state.Count++;
            Thread.Sleep(1000 + _random.Next(2000));
            Send(state);
        }
    }

    private void Send(ClientState clientState)
    {
        Console.WriteLine("Sending " + _clientId);
        byte[] buffer = Encoding.UTF8.GetBytes(string.Format("Send from Thread {0} Client id {1} Count {2}", Thread.CurrentThread.ManagedThreadId, _clientId,clientState.Count));
        clientState.WorkSocket.BeginSend(buffer, 0, buffer.Length, 0, BeginSendCallBack, clientState);
    }

    private void BeginSendCallBack(IAsyncResult ar)
    {
        var state = (ClientState) ar.AsyncState;
        int byteSent= state.WorkSocket.EndSend(ar);
        Console.WriteLine("Sent {0} bytes to server.", byteSent);
        Receive(state);
    }
}

public class ClientState
{
    // Client socket.
    public Socket WorkSocket = null;
    // Size of receive buffer.
    public const int BufferSize = 1024;
    // Receive buffer.
    public byte[] Buffer = new byte[BufferSize];

    public int Count = 0;
}

服务器

public class AsyncServer
{
    private const int Port = 9999;
    public void StartServer()
    {
        var thread = new Thread(Run) {IsBackground = true};
        thread.Start();
    }

    private void Run()
    {
        Console.WriteLine("Running");
        var tcpListener =  new TcpListener(IPAddress.Loopback, Port);
        tcpListener.Start();
        while (true)
        {
            Console.WriteLine("Before Accept");
            var state = new ServerState {WorkSocket = tcpListener.AcceptSocket()};
            Console.WriteLine("Before Recieve");
            Receive(state);
        }
    }

    private void Receive(ServerState state)
    {
        state.WorkSocket.BeginReceive(state.Buffer, 0, ServerState.BufferSize, 0, ReceiveCallBack, state);
    }

    private void ReceiveCallBack(IAsyncResult ar)
    {
        Console.WriteLine("ReceiveCallBack");
        var state = (ServerState) ar.AsyncState;
        try
        {
            int byteReceived= state.WorkSocket.EndReceive(ar);
            if (byteReceived > 0)
            {
                var receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
                Console.WriteLine("Received: " + receivedString);
                var bytesToSend = Encoding.UTF8.GetBytes("Server Got --> " + receivedString);
                Array.Copy(bytesToSend, state.Buffer, bytesToSend.Length);
                state.WorkSocket.Send(state.Buffer, 0, bytesToSend.Length, SocketFlags.None);
                Array.Clear(state.Buffer, 0, state.Buffer.Length);
                Receive(state);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    private class ServerState
    {
        public const int BufferSize = 1024;
        public readonly byte[] Buffer = new byte[1024];
        public Socket WorkSocket;
    }

我一直在使用一个控制台,你可以有两个应用程序或只启动客户端和服务器单独运行这一点。

I have run this using a console you can either have two applications or just launch the client and server separately.

   static void Main(string[] args)
    {
        if (args.Length != 0)
        {
            var server = new AsyncServer();
            server.StartServer();
        }
        else
        {
            for(int i = 0; i < 10; i++)
            {
                var client = new AsyncClient(i);
                client.StartClient();
            }
        }
        Console.WriteLine("Press a key to exit");
        Console.ReadKey();
    }