TCP客户端服务器问题

时间:2009-08-17 09:13:48

标签: c# sockets tcp

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

        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个客户。

4 个答案:

答案 0 :(得分:2)

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

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

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

    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;

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

至少,您缺少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();
}