【问题标题】:How to have a C# TCP Chat Server listen for connections from multiple clients?如何让 C# TCP 聊天服务器监听来自多个客户端的连接?
【发布时间】:2022-06-08 07:09:05
【问题描述】:

所以这是我用 c# 编写的基于 TCP 的聊天服务器的代码。通过 ipv4 连接两台计算机进行聊天没有问题,但我希望服务器程序监听并接受,然后向加入的计算机发送“成功加入”消息。

我想知道有没有办法改变这个代码来做到这一点?

服务器代码:

IPAddress ipAd = IPAddress.Parse(IPV4.Text); //use local m/c IP address, and use the same in the client

/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 8001);

/* Start Listeneting at the specified port */
myList.Start();

MessageBox.Show(\"The server is running at port 8001...\");
MessageBox.Show(\"The local End point is  :\" + myList.LocalEndpoint);
MessageBox.Show(\"Looking for other computer\");

Socket s = myList.AcceptSocket();
Console.WriteLine(\"Found buddy \" + s.RemoteEndPoint);

ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes(satt.Text));
MessageBox.Show(\"The message \" + satt.Text + \" was sent to the computer with IP address \" + IPV4.Text);

byte[] b = new byte[100];
int k = s.Receive(b);
for (int i = 0; i < k; i++)
    Console.Write(Convert.ToChar(b[i]));
    
    /* clean up */
    s.Close();
    myList.Stop();

客户端代码:

TcpClient tcpclnt = new TcpClient();

tcpclnt.Connect(RecieveIPAdd.Text, 8001); // use the ipaddress as in the server program

MessageBox.Show(\"Connected\");

Stream stm = tcpclnt.GetStream();

MessageBox.Show(\"Listening for attack information......\");

byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
string atk = Encoding.UTF8.GetString(bb.AsSpan(0, k));

谢谢你。

// Code after help

private void Connectnattk_DoWork(object sender, DoWorkEventArgs e)
        {
            {

                {
                    try
                    {
                        IPAddress ipAd = IPAddress.Parse(IPV4.Text); //use local m/c IP address, and use the same in the client

                        /* Initializes the Listener */
                        TcpListener myList = new TcpListener(ipAd, 8001);

                        /* Start Listeneting at the specified port */
                        myList.Start();

                        MessageBox.Show(\"The server is running at port 8001...\");
                        MessageBox.Show(\"The local End point is  :\" + myList.LocalEndpoint);
                        MessageBox.Show(\"Looking for other computer\");

                        Socket s = myList.AcceptSocket();
                        Console.WriteLine(\"Found buddy \" + s.RemoteEndPoint);

                        ASCIIEncoding asen = new ASCIIEncoding();
                        s.Send(asen.GetBytes(satt.Text));
                        MessageBox.Show(\"The command \" + satt.Text + \" was sent to the computer with IP address \" + IPV4.Text);

                        byte[] b = new byte[100];
                        int k = s.Receive(b);
                        for (int i = 0; i < k; i++)
                            Console.Write(Convert.ToChar(b[i]));

                        void ServerStart()
                        {

                            TcpListener listener = new TcpListener(IPAddress.Any, 8001);

                            listener.Start();
                            Console.WriteLine(\"Listening on port: 8001\");

                            while (true)
                            {
                                TcpClient client = listener.AcceptTcpClient();

                                ThreadPool.QueueUserWorkItem(state => HandleConnection(client));
                            }
                        }

                    void HandleConnection(TcpClient client)
                        {
                            Socket s = myList.AcceptSocket();
                            Console.WriteLine(\"Found buddy \" + s.RemoteEndPoint);

                            ASCIIEncoding asen = new ASCIIEncoding();
                            s.Send(asen.GetBytes(satt.Text));

                            Console.WriteLine(\"Number of connected buddies: \" + connectedbuddies++);

                            client.Close();
                        }


                        /* clean up */

                        s.Close();
                        myList.Stop();

                    }
  • 请注意,当您进行 TCP 接收时,您必须循环直到接收到所有数据。这也意味着您必须知道消息的大小
  • 一个字符/一个字母。
  • 您的客户端代码在接收中显示 100,您是说您只发送一个字节的消息吗?

标签: c# tcp chat ipv4


【解决方案1】:

在您的代码中接受客户端套接字是同步的,因此您只能接受一个客户端,处理它然后循环以接受并处理另一个客户端。

您可以使用线程为代码添加并行性。您创建一个处理客户端套接字的方法并为客户端套接字创建一个新线程。这将允许您继续循环以接受新的传入客户端套接字连接,同时处理现有的客户端套接字连接。

static void ServerStart()
{
    TcpListener listener = new TcpListener(IPAddress.Any, 4480);

    listener.Start();
    Console.WriteLine("Listening on port: 4480");

    while (true)
    {
        // Accept the client connection before creating the thread.
        TcpClient client = listener.AcceptTcpClient();

        ThreadPool.QueueUserWorkItem(state => HandleConnection(client));
    }
}

static void HandleConnection(TcpClient client)
{
    // Insert your code here. (Do not accept socket again here)
    client.Close();
}

我创建一个新线程来使用ThreadPool 为每个TcpClient 运行HandleConnection 方法。您可以在没有 ThreadPool 的情况下创建线程,但是如果出于性能原因线程是短暂的,您将需要使用 ThreadPool 来创建它们。

【讨论】:

  • 嗨,请参阅“帮助后的代码”部分。那行得通,两台计算机都说已成功连接到服务器,但服务器仍然只将消息发送到其中一台正在侦听的计算机,这意味着 HandleConnection 没有执行?谢谢。
  • @Theoneguy您两次接受套接字,这就是它阻塞的原因。在创建线程之前,您应该只接受一次套接字。您可以使用TcpClient client = listener.AcceptTcpClient();,这是我的建议,因为您已经在使用TcpListener,或者您应该将该行替换为Socket s = myList.AcceptSocket();。我将更新我的答案以增加清晰度。
  • 有没有办法在客户端连接时运行该代码?谢谢。
  • @Theoneguy你真的不能那样做。您不知道需要多少线程,因此会产生太多或不足以处理连接。您可能想查看异步方法,已经存在关于它们接受多个客户端并且它是非阻塞的问题,但您必须学习异步编程。如果您想使用Socket 对象,只需将参数更改为HandleConnection 函数,但在创建该线程之前接受它。
  • 使用 foreach 方法怎么样?那么,对于每个连接的客户端,发送消息?那行得通吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 2015-01-12
  • 1970-01-01
  • 2021-07-10
相关资源
最近更新 更多