【问题标题】:How can I accept two or more clients in the same server c# tcp/ip如何在同一服务器中接受两个或多个客户端 c# tcp/ip
【发布时间】:2018-05-28 00:13:04
【问题描述】:

我正在尝试让我的代码接受两个或更多客户端到我的服务器程序。这是代码。我需要有关如何同时接受多个客户的代码方面的帮助。我的端口出现错误。它说“每个套接字地址(协议/网络地址/端口)通常只允许使用一次

命名空间 TCPServer { 公共部分类Form1:表格 {

    //Create TCP/IP Socket 
    Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    TcpListener mTCPListener;
    TcpClient mTCPClient = new TcpClient();
    NetworkStream serverStream;

    byte[] mRx;

    public Form1()
    {
        InitializeComponent();
    }

    void onCompleteAcceptTcpClient(IAsyncResult iar)
    {
        TcpListener tcpl = (TcpListener)iar.AsyncState;
        try
        {
            ThreadStart delegateR = new ThreadStart(() => 
            mTCPClient = tcpl.EndAcceptTcpClient(iar));

            Thread R = new Thread(delegateR);
            R.Start();
            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);
        }
    }

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

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

                //ThreadStart delegateT = new ThreadStart(() => { RefreshLot(lotId); });
                //Thread T = new Thread(delegateT);
                //T.Start();
                ThreadStart delegateT = new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
                Thread T = new Thread(delegateT);
                T.Start();
                //Begin accept tcp client (only one)
                //mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
                if (mTCPListener.Pending())
                {
                    nPort = nPort + 1;
                    mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener);
                }

        }
        catch (Exception ex)
        {
            throw ex;
        }
    }


    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 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)
                {

                    //This is the message that will be sent
                    tx = Encoding.ASCII.GetBytes("Server MESRII sent: " + tbPayload.Text + "  " + DateTime.Now);
                    mTCPClient.GetStream().BeginWrite(tx, 0, tx.Length, onCompleteWriteToClientStream, mTCPClient);
                }
            }
        }
        catch (Exception exc)
        {
            MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void btnStartListening2_Click(object sender, EventArgs e)
    {

    }


}

【问题讨论】:

  • 我对之前帖子的回答有什么问题:stackoverflow.com/questions/47799387/… 我在第一条评论中说过,您不能有来自相同 IP 地址和相同端口号的两个连接。如果您想从同一个 IP 进行测试,那么您需要两个端口号。因此,创建两个具有两个不同端口号的侦听器。让两个侦听器使用相同的接受事件。测试后,您可以消除第二个听众。客户端在大型网络上尝试多个端口号和多个服务器的连接很常见。
  • 如何分配不同的端口号“让我们动态地说”?如果不是两个客户,而是另一个...
  • 服务器端口号永远不会动态分配。它们总是预先分配给一个端口号或一系列端口号。在客户端,您要么检查以确保另一个应用程序没有使用与同一服务器相同的端口号,要么尝试在一个端口号上建立连接,如果连接失败,请尝试该范围内的下一个端口号。使用 TCP,您只能有一个具有相同三个参数的连接 1) 源 IP 地址 2) 目标 IP 地址 3) 端口号。

标签: c# sockets tcp


【解决方案1】:

你应该在你的服务器上创建一个TcpListener,因为只有一个监听器可以使用一个端口。 当您获得新连接(AcceptTcpClient 方法)时,您可以开始与客户端进行消息交换的新线程。 你可以在this question看到很好的例子

【讨论】:

  • 开始一个新线程是一种非常糟糕的做法。您应该为此使用异步 API。对于小型服务器来说,为每个客户端启动一个新线程可能没问题,但最终会在连接了许多客户端的服务器上导致崩溃。
【解决方案2】:

我正在编写代码并接受了提供的所有建议。我所做的是 Call the Start 以这种方式听...

`private void btnStartListening_Click_1(object sender, EventArgs e) { 尝试 { 索引++;

            IPAddress ipaddr = IPAddress.Any;
            int x = Convert.ToInt32(tbPort.Text);
            int nPort = x;


            //#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

            if (nPort >= 23000)
            {
                nPort = nPort + 1;
                mTCPListener = new TcpListener(ipaddr, nPort);

                //Start Listening on port nPort + 1
                mTCPListener.Start();
                testingThreadStart.Add(new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener)));
                //ThreadStart delegateT = new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
                testingThread.Add(new Thread(testingThreadStart[index]));
                //Thread T = new Thread(delegateT);
                //T.Start();
                testingThread[index].Start();
                //Begin accept tcp client (only one)
                //mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
            }
            else
            {
                mTCPListener = new TcpListener(ipaddr, nPort + 1);

                //Start Listening on port 23000
                mTCPListener.Start();

                ThreadStart delegateT = new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
                Thread T = new Thread(delegateT);
                T.Start();

            }
        }`

还在代码开头添加了线程列表...

 List<ThreadStart> testingThreadStart = new List<ThreadStart>();
    List<Thread> testingThread = new List<Thread>();

这就是它的工作原理。如果有人需要/想要完整的代码,我可以发布它。对于未来的例子。

【讨论】:

    猜你喜欢
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 2016-10-05
    • 2011-02-21
    • 2014-08-18
    • 1970-01-01
    相关资源
    最近更新 更多