TcpClient.Close()仅适用于Thread.Sleep()

Vor*_*326 7 c# tcp tcpclient thread-sleep

我有简单的服务器从客户端获取字符串并将其打印在屏幕上.我也有简单的客户端,发送数据和关闭:

static void Main()
{
        var client = new TcpClient("localhost", 26140);

        var stream = client.GetStream();
        Byte[] data = System.Text.Encoding.UTF8.GetBytes("CALC qwer"); 
        stream.Write(data, 0, data.Length);
        stream.Close();
        client.Close();
        //Thread.Sleep(100);
}
Run Code Online (Sandbox Code Playgroud)

并且使用未注释的字符串'Thread.Sleep(100)'它可以正常工作.但是在评论时,有时候(5-10次运行中的1次)客户端不会发送字符串.看着wireshark和netstat我注意到客户端发送SYN,ACK包,建立连接并退出而不发送任何内容而不关闭套接字.

任何人都可以解释这种行为吗?睡眠有帮助吗?我究竟做错了什么?

UPD:

有了这个示例代码,在关闭之前添加flush()确实有效,感谢Fox32.

但在它之后我回到了我的初始代码:

var client = new TcpClient("localhost", 26140);
client.NoDelay = true;
var stream = client.GetStream();
var writer = new StreamWriter(stream);
writer.WriteLine("CALC qwer");
writer.Flush();
stream.Flush();
stream.Close();
client.Close();
Run Code Online (Sandbox Code Playgroud)

即使使用NoDelay,它也无法正常工作.这很糟糕 - 在网络流上使用StreamWriter?

UPD:

这是服务器代码:

static void Main(string[] args)
    {
        (new Server(26140)).Run();
    }
Run Code Online (Sandbox Code Playgroud)

在Server类中:

public void Run()
    {
        var listener = new TcpListener(IPAddress.Any, port);
        listener.Start();
        while (true)
        {
            try
            {
                var client = listener.AcceptTcpClient();
                Console.WriteLine("Client accepted: " + client.Client.RemoteEndPoint);
                var stream = client.GetStream();
                stream.ReadTimeout = 2000;
                byte[] buffer = new byte[1000];
                stream.Read(buffer, 0, 1000);
                var s = Encoding.UTF8.GetString(buffer);
                Console.WriteLine(s);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR! " + ex.Message);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

UPD:

添加均匀睡眠(1)会导致同时运行的30-50个客户端中的1个发生崩溃.添加睡眠(10)似乎完全解决了,我无法抓住任何崩溃.不明白,为什么socket需要这几毫秒来正确关闭.

Fox*_*x32 5

TcpClient是使用Nagle算法和更多的数据等待通过网络发送之前.如果快速关闭套接字,则不会传输任何数据.

您有多种方法可以解决此问题:

NetworkStream有一个Flush冲洗流内容的方法(我不知道如果这个方法从MSDN上的评论做任何事情)

禁用Nagle算法:设置NoDelayTcpCLient为true.

最后一个选项是设置LingerStateTcpClient.Close方法文档说明了LingerState在调用时使用的方法Close


Vor*_*326 0

我已经尝试过代码,在几台计算机上重现了这个错误。没有人崩溃。看来这是我本地计算机的错误。

感谢大家试图帮助我。

无论如何,这太奇怪了。如果我能找出我的计算机上存在此错误的原因,我会写下来。