【问题标题】:TCP Client Server ProblemTCP客户端服务器问题
【发布时间】:2009-08-17 20:13:31
【问题描述】:

我有以下服务器应用程序代码:

        TcpListener recSock = new TcpListener(400);
        recSock.Start();
        TcpClient client = recSock.AcceptTcpClient();
        NetworkStream netStream = client.GetStream();

        Byte[] data = new Byte[256];

        int i;

        while((i = netStream.Read(data, 0, data.Length)) != 0) {
            string cmd = ASCIIEncoding.ASCII.GetString(data, 0, i);
            Console.WriteLine(cmd);
            if(cmd == "R") {
                RestartScheduler();
            }
        }

        client.Close();

客户端看起来像:

        TcpClient client = new TcpClient();
        client.Connect("VM-SCHEDULER", 400);
        NetworkStream netStream = client.GetStream();
        Byte[] data = ASCIIEncoding.ASCII.GetBytes("R");
        netStream.Write(data, 0, data.Length);
        netStream.Flush();
        client.Close();

客户端第一次连接读取“R”命令并调用RestartScheduler()方法时一切正常,但是所有后续命令都失败,直到服务器重新启动。

我在第一次尝试后使用 telnet 连接到服务器,但它仍在侦听端口。

我哪里错了?

编辑:

基本上我想要完成的是服务器将始终监听,然后客户端将连接发送“R”命令然后关闭连接。客户端必须能够随时连接到服务器才能发出命令。任何时候都只会有 1 个客户。

【问题讨论】:

  • 在这种情况下,请查看我的更新答案。

标签: c# sockets tcp


【解决方案1】:

如果没有要读取的数据,netStream.Read 将返回 0 并且您的 while 循环将退出,在 client.Close(); 处断开客户端连接。您的代码中没有任何内容允许服务器在这种情况下继续接收。

您需要一直监听连接直到应用程序关闭,所以将监听和 GetStream 放在一个 while 循环中。由于 Stream.Read 是一个阻塞调用,因此您应该有一些数据用于读取 while 循环的数据(除非发生超时)。否则它将关闭连接并返回侦听新连接。

注意:这里我没有包含任何错误处理,您需要自己添加。

    TcpListener recSock = new TcpListener(400);
    recSock.Start();

    while (!stopping)
    {
        TcpClient client = recSock.AcceptTcpClient();
        NetworkStream netStream = client.GetStream();

        Byte[] data = new Byte[256];

        int i = netStream.Read(data, 0, data.Length);

        while(i != 0) 
        {
            string cmd = ASCIIEncoding.ASCII.GetString(data, 0, i);
            Console.WriteLine(cmd);
            if(cmd == "R") {
                RestartScheduler();
            }
            i = stream.Read(bytes, 0, bytes.Length);
        }

        client.Close();

        Thread.Sleep(1); // Will allow the stopping bool to be updated
    }

模块级添加:

    private bool stopping = false;

在您的关机功能中:

    stopping = true;

【讨论】:

    【解决方案2】:

    您是在多次连接,还是在同一个连接上发送多个命令?如果你能提供一个简短但完整的程序来演示这个问题,那真的很有帮助。

    我的猜测是,由于一次从单个连接读取多个命令,您遇到了问题,但如果没有更多信息,很难知道。不要忘记,从客户端对Write 的一次调用很容易导致在服务器端进行多次读取——反之亦然。

    【讨论】:

      【解决方案3】:

      那么服务器将在收到第一个命令后退出,不是吗?

      【讨论】:

        【解决方案4】:

        至少,您缺少using 语句:

        TcpListener recSock = new TcpListener(IPAddress.Loopback,  400);
        recSock.Start();
        using (TcpClient client = recSock.AcceptTcpClient())
        {
            using (NetworkStream netStream = client.GetStream())
            {
                Byte[] data = new Byte[256];
        
                int i;
        
                while ((i = netStream.Read(data, 0, data.Length)) != 0)
                {
                    string cmd = Encoding.ASCII.GetString(data, 0, i);
                    Console.WriteLine(cmd);
                    if (cmd == "R")
                    {
                        RestartScheduler();
                    }
                }
            }
        
            client.Close();
        }
        

        using (TcpClient client = new TcpClient())
        {
            client.Connect("VM-SCHEDULER", 400);
            using (NetworkStream netStream = client.GetStream())
            {
                Byte[] data = Encoding.ASCII.GetBytes("R");
                netStream.Write(data, 0, data.Length);
                netStream.Flush();
            }
            client.Close();
        }
        

        【讨论】:

          猜你喜欢
          • 2022-01-22
          • 2011-08-14
          • 2020-07-15
          • 1970-01-01
          • 2015-08-29
          • 2012-07-04
          • 2012-08-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多