创建多线程环境中的C#异步套接字客户端 [英] create c# asynchronous socket client in multithreaded environment

查看:101
本文介绍了创建多线程环境中的C#异步套接字客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create asynchronous socket client in multithreaded environment but it is not working correctly. As below sample code, If i create new AsyncSocketClient and call StartClent from multi-threaded environment it will process only one or two for rest, it is not processing.(I am creating new AsyncSocketClient with every new request) Is it because of static variables,

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

    }


推荐答案

下面是一个非阻挡客户端和服务器与实现了一个简单的回波的一个例子。没有错误检查,并没有什么正确关闭它应该做的。该服务器具有一定的同步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();
    }

这篇关于创建多线程环境中的C#异步套接字客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆