TcpClient.Close () only works with Thread.Sleep ()

I have a simple server that receives a string from a client and prints it on the screen. I also have a simple client sending data and closing:

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);
}

And with uncommented string 'Thread.Sleep (100)' works fine. But when commenting, sometimes (1 out of 5-10 starts) the client does not send the line. Watching wirehark and netstat, I noticed that the client sends SYN, an ACK packet, establishes a connection and exits without sending anything and without closing the socket.

Can anyone explain this behavior? Why does sleep help? What am I doing wrong?

UPD:

With this code example, adding flush () before closing really works, thanks Fox32.

But after that I returned to the source code:

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();

, NoDelay. - StreamWriter ?

UPD:

:

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

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);
            }
        }
    }

UPD:

Sleep (1) 30-50 , . Sleep (10), , , . , , .

+5
5

, . . .

, .

, . , , .

0

TcpClient Nagle , . , .

:

NetworkStream Flush ( , MSDN)

Nagle: NoDelay TcpClient true.

- LingerState TcpClient. Close , LingerState Close

+5

Shutdown Socket TcpClient, . .

TCP.

NoDelay , . Flush IMHO - . , , , . Shutdown.

, Shutdown, Socket, , . Flush . - - . Close, Close .

TcpClient , Socket, :

tcpClient.Client.Shutdown();
tcpClient.Close();

Reflector, - GetStream, , Close . , , Shutdown. , - . .

+4

Read() , , . , . . .

. . , NoDelay Close() Flush(), Using , .

class Program
{
    static int port = 123;
    static string ip = "1.1.1.1";
    static AutoResetEvent waitHandle = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        StartServer();
        waitHandle.WaitOne();

        for (int x=0; x<1000; x++)
        {
            StartClient(x);
        }

        Console.WriteLine("Done starting clients");
        Console.ReadLine();
    }

    static void StartClient(int count)
    {
        Task.Factory.StartNew((paramCount) =>
        {
            int myCount = (int)paramCount;

            using (TcpClient client = new TcpClient(ip, port))
            {
                using (NetworkStream networkStream = client.GetStream())
                {
                    using (StreamWriter writer = new StreamWriter(networkStream))
                    {
                        writer.WriteLine("hello, tcp world #" + myCount);
                    }
                }
            }
        }, count);
    }

    static void StartServer()
    {
        Task.Factory.StartNew(() => 
        {
            try
            {
                TcpListener listener = new TcpListener(port);
                listener.Start();

                Console.WriteLine("Listening...");
                waitHandle.Set();

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

                    Task.Factory.StartNew((paramClient) => {
                        TcpClient client = (TcpClient)paramClient;

                        byte[] buffer = new byte[32768];
                        MemoryStream memory = new MemoryStream();
                        using (NetworkStream networkStream = client.GetStream())
                        {
                            do
                            {
                                int read = networkStream.Read(buffer, 0, buffer.Length);
                                memory.Write(buffer, 0, read);
                            }
                            while (networkStream.DataAvailable);
                        }

                        string text = Encoding.UTF8.GetString(memory.ToArray());
                        Console.WriteLine("from client: " + text);
                    }, theClient);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }, TaskCreationOptions.LongRunning);
    }
}
+1

UPD:

. , .

ENDOFUPD

, . @Despertar - . . . .

: ( ), ( ) ( exe ).

, , . ulility 150 , , 5-10 ( ). uncommenting Thread.Sleep() , .

- ?

:

private static void Main(string[] args)
{
try
{
    using (TcpClient client = new TcpClient(ip, port))
    {
        using (NetworkStream networkStream = client.GetStream())
        {
            using (StreamWriter writer = new StreamWriter(networkStream))
            {
                writer.WriteLine("# hello, tcp world #");
                writer.Flush();
            }
            networkStream.Flush();
            networkStream.Close();
        }
        client.Close();
        //Thread.Sleep(10);
     }
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex.Message);
     }
}

Code, launching the client several times (compile it in an exe file and put exe next to the client - this code will run many clients one by one):

static void Main(string[] args)
{
    string path = "YOU_CLIENT_PROJECT_NAME.exe";
    for (int i = 0; i < 150; i++ )
    {
        Console.WriteLine(i);
        Process.Start(path);
        Thread.Sleep(50);
    }
    Console.WriteLine("Done");
    Console.ReadLine();
}

(do not forget to change the path to the corrent exe file name)

Server Code:

class Program
{

    static int port = 26140;
    static AutoResetEvent waitHandle = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        StartServer();
        waitHandle.WaitOne();
        Console.ReadLine();
    }

    static void StartServer()
    {
        Task.Factory.StartNew(() =>
        {
            try
            {
                TcpListener listener = new TcpListener(port);
                listener.Start();

                Console.WriteLine("Listening...");
                waitHandle.Set();

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

                    Task.Factory.StartNew(paramClient =>
                    {
                        try
                        {
                            TcpClient client = (TcpClient) paramClient;
                            byte[] buffer = new byte[32768];
                            MemoryStream memory = new MemoryStream();
                            using (NetworkStream networkStream = client.GetStream())
                            {
                                networkStream.ReadTimeout = 2000;
                                do
                                {
                                    int read = networkStream.Read(buffer, 0, buffer.Length);
                                    memory.Write(buffer, 0, read);
                                } while (networkStream.DataAvailable);
                                string text = Encoding.UTF8.GetString(memory.ToArray());
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("ERROR: " + e.Message);
                        }
                    }, theClient);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }, TaskCreationOptions.LongRunning);
    }
}
0
source

All Articles