1

I'm writing a code in c# to have a tcp server that accepts multiple client at the same time. How can I implemet that in my code?

Here is my code, it's in form code. I have a button to start listening, and only accepts one client.

Pd: I'm using Visual Studio 2010.

public partial class Form1 : Form
{
    TcpListener mTCPListener;
    TcpClient mTCPClient = new TcpClient();
    NetworkStream serverStream;
    byte[] mRx;

    public Form1()
    {
        InitializeComponent();
    }

    void onCompleteAcceptTcpClient(IAsyncResult iar)
    {
        TcpListener tcpl = (TcpListener)iar.AsyncState;
        try
        {
            mTCPClient = tcpl.EndAcceptTcpClient(iar);
            printLine("Client Connected...");

            //Begin Asynchronous Read
            mRx = new byte[1024];
            mTCPClient.GetStream().BeginRead(mRx, 0, mRx.Length, onCompleteReadFromTCPClientStream, mTCPClient);
        }
        catch (Exception exc)
        {
            MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    void onCompleteReadFromTCPClientStream(IAsyncResult iar)
    {
        TcpClient tcpc;
        int nCountReadBytes = 0;
        string strRecv;
        try
        {
            tcpc = (TcpClient)iar.AsyncState;
            nCountReadBytes = tcpc.GetStream().EndRead(iar);

            if (nCountReadBytes == 0)
            {
                MessageBox.Show("Client disconnected.");
                return;
            }

            strRecv = Encoding.ASCII.GetString(mRx, 0, nCountReadBytes);
            printLine(strRecv);
            mRx = new byte[1024];
            tcpc.GetStream().BeginRead(mRx, 0, mRx.Length, onCompleteReadFromTCPClientStream, tcpc);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    public void printLine(string _strPrint)
    {
        tbConsoleOutput.Invoke(new Action<string>(doInvoke), _strPrint);
    }

    public void doInvoke(string _strPrint)
    {
        tbConsoleOutput.Text = _strPrint + Environment.NewLine + tbConsoleOutput.Text;
    }

    private void onCompleteWriteToClientStream(IAsyncResult iar)
    {
        try
        {
            TcpClient tcpc = (TcpClient)iar.AsyncState;
            tcpc.GetStream().EndWrite(iar);
        }
        catch (Exception exc)
        {
            MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void btnStartListening_Click_1(object sender, EventArgs e)
    {
        try
        {
            IPAddress ipaddr;
            int nPort;

            #region Validating IP Address
            if (!int.TryParse(tbPort.Text, out nPort))
            {
                nPort = 23000;
            }
            if (!IPAddress.TryParse(tbIPAddress.Text, out ipaddr))
            {
                MessageBox.Show("Invalid IP address supplied.");
                return;
            }
            #endregion
            mTCPListener = new TcpListener(ipaddr, nPort);

            //Start Listening
            mTCPListener.Start();
            mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    private void btnSend_Click_1(object sender, EventArgs e)
    {
        byte[] tx = new byte[1024];
        if (string.IsNullOrEmpty(tbPayload.Text)) return;
        try
        {
            if (mTCPClient != null)
            {
                if (mTCPClient.Client.Connected)
                {
                    tx = Encoding.ASCII.GetBytes(tbPayload.Text);
                    mTCPClient.GetStream().BeginWrite(tx, 0, tx.Length, onCompleteWriteToClientStream, mTCPClient);
                }
            }
        }
        catch (Exception exc)
        {
            MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}
FortyTwo
  • 2,414
  • 3
  • 22
  • 33
Christian
  • 11
  • 3
  • You can call `BeginAcceptTcpClient` again in `onCompleteAcceptTcpClient`. But what if there is more that `1024 bytes` to read/write? – Rickless Dec 13 '17 at 17:58
  • You do not need to do anything. Listener will accept multiple connections as long as the port number is the same and the source IP is different for each connection. Every time a new connection is made in the Accept method you need to add the socket to a List<> object so you have a complete list of active connections. Normally I create a state object and put the socket into the state object and then add additional properties so you track each connection. So I end up with a List instead of List – jdweng Dec 13 '17 at 18:03
  • Mahmoud : There is no issue with number of bytes per message as long as you do not close connection after each message. The BeginRead() event is calling BeginRead() so the connection stays open. – jdweng Dec 13 '17 at 18:05
  • @jdweng Yes, `onCompleteReadFromTCPClientStream` call `BeginRead` again. I notice this right now so the number of bytes is not an issue. But this code will still accept a single connection. `BeginAcceptTcpClient ` is called once. – Rickless Dec 13 '17 at 18:09
  • @jdweng you have an example on how to use the list of users connected? – Christian Dec 13 '17 at 18:34
  • I made a complicated server in June that accepts multiple clients and has an application layer. I tested it with multiple clients. The OP was plaining on accepting up to 500 clients with code : https://stackoverflow.com/questions/44471975/gps-socket-communication-concox – jdweng Dec 13 '17 at 19:00
  • Okay, so How can I create the list for the new connections? (Sorry i'm a rookie at this) – Christian Dec 13 '17 at 23:33

0 Answers0