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

时间:2014-10-28 16:58:23

标签: c# multithreading sockets asynchronous

我正在尝试在多线程环境中创建异步套接字客户端,但它无法正常工作。 如下面的示例代码, 如果我创建新的AsyncSocketClient并从多线程环境调用StartClent,它将只处理一个或两个休息,它不处理。(我正在为每个新请求创建新的AsyncSocketClient) 是因为静态变量,

 class AsyncSocketClient
    {

        private static AutoResetEvent sendDone =
            new AutoResetEvent(false);
        private static AutoResetEvent receiveDone =
            new AutoResetEvent(false);

        private static ManualResetEvent connectDone =
new ManualResetEvent(false);

       static private String response = "";


        public void StartClent()
        {


            Socket workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           // clientSock.ReceiveTimeout = 1;


            try
            {
                workSocket.BeginConnect(new IPEndPoint(IPAddress.Loopback, 8080), new AsyncCallback(ConnectCallBack), workSocket);
                connectDone.WaitOne();


                Send(s.workSocket, "<EOF>");
                sendDone.WaitOne();

                Receive(workSocket);
                receiveDone.WaitOne();


            }
            catch(Exception ex)
            {

            }
        }

        private void ConnectCallBack(IAsyncResult ar)
        {
            Socket workSocket = (Socket)ar.AsyncState;
            workSocket.EndConnect(ar);
            connectDone.Set();
        }

        private void Receive(Socket client)
        {
            StateObject state = new StateObject();
            state.workSocket = client;
           client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
        }

        private void ReceiveCallBack(IAsyncResult ar)
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            int byteReceived= client.EndReceive(ar);
            if (byteReceived > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, state.buffer.Length));
                Array.Clear(state.buffer, 0, state.buffer.Length);
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
            }
            else
            {
                if (state.sb.Length > 1)
                {
                    response = state.sb.ToString();
                }
                receiveDone.Set();
            }
        }

        private void Send(Socket client,string data)
        {
            byte[] sendBufer = Encoding.ASCII.GetBytes(data);
            client.BeginSend(sendBufer, 0, sendBufer.Length, 0, new AsyncCallback(BeginSendCallBack), client);

        }

        private void BeginSendCallBack(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
          int byteSent= client.EndSend(ar);
          Console.WriteLine("Sent {0} bytes to server.", byteSent);
            sendDone.Set();
        }



    }

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

    }

1 个答案:

答案 0 :(得分:0)

以下是一个非阻塞客户端和服务器的示例,其中实现了简单的回显。没有错误检查,没有正确关闭,应该做什么。服务器有一些同步代码,只是为了让它更容易理解。

客户

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;
    }

我使用控制台运行此操作,您可以拥有两个应用程序,也可以单独启动客户端和服务器。

   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();
    }