none
C# TcpClient can not run successfully the second time RRS feed

  • Question

  • I found some strange issue: I need to use TCP socket to send an encrypted (or signed) byte array (byte[]) to remote server to request some information.
    If the encrypted data is correct, I can get correct feed back; if not, I can see some exception.
    But the wired thing is: for the first time I run my program, I always get the correct information feed back, but if I slept a few seconds, and try again, then I always get exceptions.
    The following is my code:

    private static string sendMessage(byte[] sendBytes)
    {
        const int bytesize = 1024 * 1024;
        string answer = "";
        try 
        {
        TcpClient client = new TcpClient("1.2.3.4", 1234);
        client.SendTimeout = 3000;
        client.ReceiveTimeout = 5000;
        NetworkStream stream = client.GetStream();
        stream.Write(sendBytes, 0, sendBytes.Length);
        byte[] messageBytes = new byte[bytesize];
        stream.Read(messageBytes, 0, messageBytes.Length);
        answer = Encoding.UTF8.GetString(messageBytes);
        client.Close();
        return (answer);
        }
        catch (Exception e) // Catch exceptions  
        {
        Console.WriteLine(e.Message);
        return (answer);
        }
        //return (answer);
    }
    
    static void Main(string[] args)
    {
        var take1 = sendMessage(Encoding.UTF8.GetBytes("Hello World!"));
        Thread.Sleep(10000);
        var take2 = sendMessage(Encoding.UTF8.GetBytes("Hello World!"));
        Console.WriteLine("Take1 = {0}, take2 = {1}", take1, take2);
    }
    

    To make things simply, I omit all the enctrypted process, as it should be the same. 

    The exception is at this line: Console.WriteLine(e.Message);

    The error message is: "Unable to read data from the transport connection: ."

    The same exception only happen after the first run.  So, my program always works for the first time run, but since the second, third time, I always get exception.

    Any idea why this could happen?  How I can solve this?  I was thinking if I destroy the TcpClient instance each time after I send and receive the message, it should be the same as I run the program from scratch, right?  But how I can do this?

    Saturday, October 13, 2018 6:25 PM

Answers

  • Hi zydjohn,

    I think it is a server side issue, I would suggest that you could contract the developer of server side to help you debug it at server side.

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by zydjohn Tuesday, October 16, 2018 7:52 AM
    Tuesday, October 16, 2018 3:18 AM
    Moderator

All replies

  • https://www.techopedia.com/definition/25646/using-statement-c

    <copied>

    The using statement is useful for objects whose lifetimes are within the method or block in which they are created. This statement reduces the code in which resource-intensive operations are performed by providing simpler syntax and eliminating the need for multiple calls to release the resources at the end of their scope.

    <end>

    using(var client = new TcpClient("1.2.3.4", 1234)
    {
       try
       {
    
       }
       catch
       {
    
       }
    }



    • Edited by DA924x Saturday, October 13, 2018 11:21 PM
    Saturday, October 13, 2018 8:27 PM
  • Hello:

    I modified my code according to your advice, but still I got the same exception.  The result is the same: first time OK, second time not OK.

    Any more ideas?

    Thanks

    Sunday, October 14, 2018 8:15 AM
  • Can you post the code?
    Sunday, October 14, 2018 4:24 PM
  • Hi, 

    The following is my code after the modification:

    private static string sendMessage(byte[] sendBytes)
    {
        const int bytesize = 1024 * 1024;
        string answer = "";
        using (TcpClient client = new TcpClient("1.2.3.4", 1234))
        {
        try
        {
        client.SendTimeout = 3000;
        client.ReceiveTimeout = 5000;
        NetworkStream stream = client.GetStream();
        stream.Write(sendBytes, 0, sendBytes.Length);
        byte[] messageBytes = new byte[bytesize];
        stream.Read(messageBytes, 0, messageBytes.Length);
        answer = Encoding.UTF8.GetString(messageBytes);
        }
        catch (Exception e) // Catch exceptions   
        {
        Console.WriteLine(e.Message);
        }
        }
        return (answer);
    }
    
    static void Main(string[] args)
    {
        var take1 = sendMessage(Encoding.UTF8.GetBytes("Hello World!"));
        Thread.Sleep(10000);
        var take2 = sendMessage(Encoding.UTF8.GetBytes("Hello World!"));
        Console.WriteLine("Take1 = {0}, take2 = {1}", take1, take2);
    }

    I can't see anything wrong with the code, but I wounder there could be some settings on the remote server side.  But no idea how to fix the issue.

    Sunday, October 14, 2018 8:45 PM
  • You can try setting stream = null to set the object to a null value within the using block to  destroy it basically. But you would think  that it being  in a using block, that it  would take care of destroying the object.
    Sunday, October 14, 2018 10:14 PM
  • Hi zydjohn,

    Based on your description, I create a simple sample with related service(code below), which works well. Maybe the issue is caused by socket server instead of client. 

    #Server 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace SocketServer1
    {
        class Program
        {
            static readonly object _lock = new object();
            static readonly Dictionary<int, TcpClient> list_clients = new Dictionary<int, TcpClient>();
    
    
            static void Main(string[] args)
            {
                int count = 1;
    
                TcpListener ServerSocket = new TcpListener(IPAddress.Any, 5000);
                ServerSocket.Start();
    
                while (true)
                {
                    TcpClient client = ServerSocket.AcceptTcpClient();
                    lock (_lock) list_clients.Add(count, client);
                    Console.WriteLine("Someone connected!!");
    
                    Thread t = new Thread(handle_clients);
                    t.Start(count);
                    count++;
                }
    
            }
    
            public static void handle_clients(object o)
            {
                int id = (int)o;
                TcpClient client;
    
                lock (_lock) client = list_clients[id];
    
                while (true)
                {
                    NetworkStream stream = client.GetStream();
                    byte[] buffer = new byte[1024];
                    int byte_count = stream.Read(buffer, 0, buffer.Length);
    
                    if (byte_count == 0)
                    {
                        break;
                    }
    
                    string data = Encoding.ASCII.GetString(buffer, 0, byte_count);
                    broadcast(data);
                    Console.WriteLine(data);
                }
    
                lock (_lock) list_clients.Remove(id);
                client.Client.Shutdown(SocketShutdown.Both);
                client.Close();
            }
    
            public static void broadcast(string data)
            {
                byte[] buffer = Encoding.ASCII.GetBytes(data + Environment.NewLine);
    
                lock (_lock)
                {
                    foreach (TcpClient c in list_clients.Values)
                    {
                        NetworkStream stream = c.GetStream();
    
                        stream.Write(buffer, 0, buffer.Length);
                    }
                }
            }
    
        }
    }
    

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, October 15, 2018 5:27 AM
    Moderator
  • Hello:

    Thank you very much for your code.  However, please note: the remote server is not under my control, I have no idea how the remote server is implemented, the only thing I can do is code a tcpClient.

    But the issue for first time OK, second time NOT OK seems to be very weird.

    Monday, October 15, 2018 6:49 AM
  • Hi zydjohn,

    Please show the detailed exception error messages, It seems that it is not client side issue, maybe server side close the TCP listen after the first request. 

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, October 15, 2018 6:54 AM
    Moderator
  • Hello:

    For the first time, there was no exception, for the second time, the error message is something like the following (I am using Windows 10 Chinese version, so the exception is in Chinese):

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    -e{System.IO.IOException: Unable to read data from the transport connection: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。. 
    ---> System.Net.Sockets.SocketException: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。
     at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
    --- End of inner exception stack trace ---
    at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
    at TCPClient1.Program.sendMessage(Byte[] sendBytes)
    System.Exception {System.IO.IOException}
    + Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
    HResult -2146232800
    HelpLink
    +  InnerException
    {System.Net.Sockets.SocketException (10060): 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。
    at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)} System.Exception {System.Net.Sockets.SocketException}
    Message "Unable to read data from the transport connection: 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。."
    Source "System.Net.Sockets" string
    StackTrace "   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
    at TCPClient1.Program.sendMessage(Byte[] sendBytes)

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    Even I changed client.ReceiveTimeout = 50000;

    Or even higher number of seconds, I still got the same exception, but the first time run, it is always OK.

    Any suggestions?

    Thanks,

    Monday, October 15, 2018 9:48 AM
  • Hi,

    you could try this:

    private static string sendMessage(byte[] sendBytes)
    {
        const int bytesize = 1024 * 1024;
        string answer = "";
        using (TcpClient client = new TcpClient("1.2.3.4", 1234))
        {
            while (true)
            {
                try
                {
                    client.SendTimeout = 3000;
                    client.ReceiveTimeout = 5000;
                    NetworkStream stream = client.GetStream();
                    stream.Write(sendBytes, 0, sendBytes.Length);
                    byte[] messageBytes = new byte[bytesize];
                    stream.Read(messageBytes, 0, messageBytes.Length);
                    answer = Encoding.UTF8.GetString(messageBytes);
                    return answer; //Escapes loop here
                }
                catch (Exception e) // Catch exceptions   
                {
                    Console.WriteLine(e.Message);
                    Thread.Sleep(1000);
                }
            }
        }
        throw new Exception("Error");
    }

    This method is trying to connect to the server again and again till it's working.

    Greetings, Chris

    Monday, October 15, 2018 6:18 PM
  • Hi,

    Thank you for your reply, I modified my code according to your advice, but the result is the same.

    By the way, the company hosting the remote server has released some .NET API.  But using their API, I also get the similar error, but the error message is a little different:

    System.IO.IOException
      HResult=0x80131620
      Message=Unable to read data from the transport connection: 远程主机强迫关闭了一个现有的连接。.

    It seems the remote server can't receive API call from the same client only once at a time.  However, my current program calls the service only once at a time, and the first time, it always works.  But no idea why the second time always fails.

    Any more suggestions?

    Monday, October 15, 2018 7:32 PM
  • Hi zydjohn,

    I think it is a server side issue, I would suggest that you could contract the developer of server side to help you debug it at server side.

    Best regards,

    Zhanglong


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by zydjohn Tuesday, October 16, 2018 7:52 AM
    Tuesday, October 16, 2018 3:18 AM
    Moderator
  • Hi zydjohn,

    This is an older thread, but I don't know if you ever solved your problem. I have recently written a blog post: Event-Driven TCP ( http://geek-goddess-bonnie.blogspot.com/2018/12/event-driven-tcp.html ).

    Along with some explanation as to how it all works, I've also included links to 2 zip files for both Client and Server (the Server is simply there for testing the Client).

    I don't know if it will help, but maybe it will give you some ideas ... and it couldn't hurt!!  ;0)


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Saturday, December 29, 2018 9:39 PM
    Moderator