【问题标题】:TCPClient is not closed, and instead waits for a client to close itTCPClient 没有关闭,而是等待客户端关闭它
【发布时间】:2017-03-16 07:19:22
【问题描述】:

我对编写 TcpListener 有一些疑问。

第一个问题:

一旦客户端使用浏览器连接,我就会看到请求。没关系。但后来我面临写作问题。和客户端接收该数据。它基本上永远不会得到服务器的回复。我需要那个冲洗功能吗?它是如何工作的 ?还有其他方法吗?

问题 2 更奇怪。当我调用 client.close() 时,客户端不会去任何地方。它仍然存在。浏览器仍在寻找数据。当我在浏览器中终止连接时,只有 Tcp 客户端关闭并重新开始循环。

namespace TestServer
{
    class Program
    {
       public static void Main()
        {
            TcpListener server;
            IPAddress addr = IPAddress.Parse("127.0.0.1");
            server = new TcpListener(addr, 80);


            server.Start();

            byte[] buffer = new byte[1024];


            while(true)
            {
                string data = null;
                Console.WriteLine("Awaiting for connections");
                TcpClient client = server.AcceptTcpClient();

                Console.WriteLine("Connected...");

                NetworkStream str = client.GetStream();

                int msgCounter;

                while ((msgCounter = str.Read(buffer, 0, buffer.Length)) != 0)
                {
                    Console.WriteLine("Processing stream...");

                    data += System.Text.Encoding.ASCII.GetString(buffer, 0, msgCounter);
                    Console.WriteLine("Reciaved: {0}", System.Text.Encoding.ASCII.GetString(buffer, 0, msgCounter));
                }


                byte[] response = System.Text.Encoding.ASCII.GetBytes("200 OK");
                str.Write(response, 0, response.Length);

                str.Flush();

                client.Close();

                buffer = new byte[1024];
            }
        }
    }
}

【问题讨论】:

  • 调试器说什么?
  • 没有错误,真的没有。
  • 但是您是否逐步完成了实施?它甚至到达client.Close() call 了吗?
  • 您确定您的客户端代码正确吗?它是否监听来自服务器的响应?
  • @NewCallum 客户端是浏览器

标签: c# server tcpclient


【解决方案1】:

TCP 作为双向传输层协议,并不表示“客户端完成发送请求”信号的任何概念。

这对开发人员来说意味着必须在应用程序(或任何其他更高级别)协议层中定义此类信号。

在您的情况下,它是由 HTTP 本身在 https://tools.ietf.org/html//rfc2616#section-5 中声明的

因此,如果您打算实现 HTTP 服务器,则必须解析 HTTP 请求,该请求具有确定的方式来识别请求的结束(请参阅上面的链接)。

总结一下:您需要以某种方式知道您已经完全阅读了请求,并且您可以开始处理它并生成/发送响应。

【讨论】:

  • 非常感谢兄弟。这拯救了我的一天。祝你好运:)
  • @AntonStafeyev 如果答案回答了您的问题,最好用绿色复选标记(在答案评分的左右下方)标记答案。
  • 关于有问题的代码,除了检测到 title 中所述的关闭之外,还有许多其他问题
  • @L.B 喜欢什么?
  • 就像线程的湖(阻塞调用server.AcceptTcpClient),假设str.Read 将返回完整的字符串(想想多字节字符)等等。
【解决方案2】:

我建议您从a million times proven working MSDN example of TcpListener class 开始。此外,我可以指出明确的错误方法:

  1. 不要重新创建缓冲区,这是浪费资源。
  2. 如果您使用 TCP 套接字,请不要将浏览器用作测试客户端。任何浏览器都试图以某种方式纠正 HTTP 协议错误,并且可以以非常不可预测的方式进行。如果您需要 HTTP 级别的调试,请使用 Fiddler,用于较低级别 - Microsoft 网络监视器、Netcat 的 Wireshark。
  3. 阅读一些有关 TCP/IP 网络的书可能会很有用。特别是,您会知道,协议定义的 TCP 连接没有“关闭”操作或命令,TcpClient 只是模拟它。相反,一个对等点可以向另一个对等点发送“关闭”,这确实意味着它不再计划发送数据,但可以读取它。只有在两个对等方都发送了“shutdown”并收到对方的“shutdown”后,才能认为连接已关闭。

【讨论】:

  • “和潜在的内存泄漏” --- 不过我不会称之为“内存泄漏”。
  • 如果您使用异步操作并遇到异常,可能会出现内存泄漏,它只是 WINSOCK 的包装,内部资源无法管理
  • 我自己看到了:)
  • 这是一个错误,应该报告。 PS:反对票不是我的。
  • 在过去的 20 年里,我错过了几次成名的机会。就是这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多