简体   繁体   中英

How to make synchronous socket asynchronous?

I have to use a socket library that only exposes synchronous socket interface. I have a few question converting this sync to async. I start from msdn sample(the library interface is similar to microsoft socket library except that the library uses different communication algorithm).

This is my current progress

    private async void Start_Click(object sender, RoutedEventArgs e)
    {
        Log("Start server");
        var port = int.Parse(Port.Text);
        var task = Task.Run(() =>
        {
            // Establish the local endpoint for the socket.
            // Dns.GetHostName returns the name of the 
            // host running the application.
            Log("Hostname " + Dns.GetHostName());

            IPAddress[] ipv4Addresses = Array.FindAll(
                Dns.GetHostEntry(string.Empty).AddressList,
                a => a.AddressFamily == AddressFamily.InterNetwork);
            IPAddress[] ipv6Addresses = Array.FindAll(
                Dns.GetHostEntry(Dns.GetHostName()).AddressList,
                a => a.AddressFamily == AddressFamily.InterNetworkV6);

            foreach (var ip in ipv4Addresses)
            {
                Log("Ipv4 list " + ip);
            }
            foreach (var ip in ipv6Addresses)
            {
                Log("Ipv6 list " + ip);
            }

            var localEndPoint = new IPEndPoint(IPAddress.Any, port);
            Log("Ip " + IPAddress.Any);
            Log("Port " + port);

            // Create a TCP/IP socket.
            var 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((int)SocketOptionName.MaxConnections);
                Log("Max connection " + (int)SocketOptionName.MaxConnections);

                // Start listening for connections.
                bool isContinue = true;
                while (isContinue)
                {
                    Log("Waiting for a connection...");
                    // Program is suspended while waiting for an incoming connection.
                    var handler = listener.Accept();


                    // handle connection
                    // Data buffer for incoming data.
                    byte[] bytes = new Byte[1024];

                    string data;

                    Log("Connection accepted");

                    Log("Local endpoint " + handler.LocalEndPoint);
                    Log("Remote endpoint " + handler.RemoteEndPoint);

                    data = null;

                    // An incoming connection needs to be processed.
                    while (true)
                    {
                        bytes = new byte[1024];
                        int bytesRec = handler.Receive(bytes);
                        data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
                        if (data.IndexOf("<EOF>") > -1)
                        {
                            break;
                        }
                    }

                    // Show the data on the console.
                    Log("Text received " + data);

                    // Echo the data back to the client.
                    byte[] msg = Encoding.ASCII.GetBytes(data);

                    handler.Send(msg);
                    Log("Message sent");

                    handler.Shutdown(SocketShutdown.Both);
                    Log("Shutdown");
                    handler.Close();
                    Log("Close");

                    isContinue = true;
                }

            }
            catch (Exception ex)
            {
                Log(ex.ToString());
            }
        });
        await task;
    }
  1. What happened when i have 2 or more concurrent client?
  2. What happened to the second connection when the first connection is busy communicating?
  3. Does the listener immediately listen after listener.Accept()?
  4. Assuming i have 4 logical cores, what happen when i listen on 4 thread each with different port number. Each of this listener is blocking the thread in listener.Accept. What will happened to my ui and pc? Will it hang(all cores are used and blocked)?
  5. Are there any pattern that i can refer on?

Im thinking of using Task, async, await, but i cant seem to construct that in my head.

I want to improve this library by adding socket.

Thanks.

If the library only exposes a synchronous implementation that means that it is performing blocking I/O. Since you can't change that as it is part of the library's implementation, you will have to make use of ThreadPool threads to delegate work. I have written a couple of blog posts that provide context into this ( 1 , 2 ).

Handling this work asynchronously would only make sense cases when you want to specifically avoid blocking a particular thread, such as a UI thread. In that case, you can simply perfom calls to the socket library like this:

var task = Task.Run(() => 
  { 
     // run socket code
  });

var result = await task;
// rest of your code

The call to Task.Run queues work to the ThreadPool and awaiting avoids blocking the UI thread while that work is performed in a separate thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM