1

I'm a newbie to C#, OOP,Networking and TCP/IP sockets...

I have a misunderstanding regarding the usage of Async TCP/IP socket communication. I'm trying to create a server which waits for several clients, and each time a client connects it displays something like "user 192.168.1.105:2421 joined"

I thought that when you use BeginAccept() a new thread will be created...whenever a new user connects, and it will take care of the communication with that specific client. However, the following code blocks...and doesn't display the message for the second client.

What should I change so that for each connected client I have a separate thread which takes care of the execution?

class Server
{
    Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    //constructor 
    public Server()
    {
        listener.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.100"), 9050));
        listener.Listen(10);
        listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
        Console.Write("Server Running...\r\n");
    }

    public void OnConnectRequest(IAsyncResult ar)
    {
        Socket listener = (Socket)ar.AsyncState;
        NewConnection(listener.EndAccept(ar));
        listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
    }

    //send a string message over a TCP socket 
    public void sendMSG(string msg,Socket socket)
    {
     //some code which sends data according to my protocol
    }

    public byte[] receiveMSG(ref Socket socket)
    {
     //some code which receives data according to my protocol
    }


    //function called whenever a NEW CLIENT is connected
    public void NewConnection(Socket sockClient)
    {
        Console.WriteLine("user {0} has joined",sockClient.RemoteEndPoint);
        byte[] msg = new byte[20];
        sockClient.Receive(msg);
    }

1 Answer 1

2

BeginAccept() accepts one single request, so your async callback will only be called once for the first request. This is the standard C# async pattern.

If you want to accept multiple requests, you need to call BeginAccept() again when you're done handling your request.

See also Asynchronous server socket multiple clients.

Edit:

You should call BeginAccept() between EndAccept() and NewConnection() if you want to permit concurrent requests:

public void OnConnectRequest(IAsyncResult ar)
{
    Socket listener = (Socket)ar.AsyncState;
    Socket accepted = listener.EndAccept(ar);
    listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
    NewConnection(accepted);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Daniel does call BeginAccept() again. But it's never executed because the thread will block before it gets there. (NewConnection() blocks on sockClient.Receive). But basically you're right: the pattern for using BeginAccept() is not right.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.