【问题标题】:TCP connection drop/ or unable to recieve data over TCPTCP 连接断开/或无法通过 TCP 接收数据
【发布时间】:2014-09-06 01:56:56
【问题描述】:

我有一台客户端 PC 使用我编写的 TCP_client 程序通过 TCP 向我发送数据。基本上,我正在向服务器发送“Hello Message”。

class Program
{
    const int ourPort = 9090;
    static IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.10"), 3000);
    static ASCIIEncoding encoder = new ASCIIEncoding();
    static System.Timers.Timer aTimer;
    static void Main(string[] args)
    {
        aTimer = new System.Timers.Timer(200);
        aTimer.Elapsed += OnTimedEvent;
        aTimer.Enabled = true;

        Console.Read();
    }

    private static void OnTimedEvent(Object source, ElapsedEventArgs e)
    {
        try
        {
            TcpClient client = new TcpClient();
            client.Connect(serverEndPoint);
            NetworkStream clientStream = client.GetStream();

            byte[] buffer = encoder.GetBytes("Hello Server!");

            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }
        catch (Exception ee)
        {
            Console.WriteLine(ee.ToString());
        }
    }

我正在使用我的 PC 通过我编写的 TCP_server 程序接收该数据。

class Server
{
    private static TcpListener tcpListener;
    static System.Timers.Timer aTimer;
    static int count = 0;
    public Server()
    {
        //
    }

    static void Main(string[] args)
    {
        tcpListener = new TcpListener(IPAddress.Any, 3000);
        tcpListener.Start();

        aTimer = new System.Timers.Timer(200);
        aTimer.Elapsed += OnTimedEvent;
        aTimer.Enabled = true;


        Console.Read();
    }

    private static void OnTimedEvent(Object source, ElapsedEventArgs e)
    {
        TcpClient client = tcpListener.AcceptTcpClient();
        Thread.Sleep(2);
        NetworkStream clientStream = client.GetStream();
        Thread.Sleep(2);

        byte[] message = new byte[4096];
        int bytesRead;

        bytesRead = 0;

        try
        {
            bytesRead = clientStream.Read(message, 0, 4096);
            client.Close();
        }
        catch (Exception ee)
        {
            Console.WriteLine("socket error");
            Console.WriteLine(ee.ToString());
            client.Close();
        }

        if (bytesRead == 0)
        {
            client.Close();
        }
        count++;

        ASCIIEncoding encoder = new ASCIIEncoding();
        Console.WriteLine(count + " " + encoder.GetString(message, 0, bytesRead));
    }

话虽如此,我看到的问题是有时我会在 TCP_server 程序的Catch() 中遇到“套接字错误”。

错误:

System.IO.IOException: Unable to read data from the transport connection: An exi
sting connection was forcibly closed by the remote host. ---> System.Net.Sockets
.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size,
 SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 s
ize)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 s
ize)
   at test_tcp_manager.Server.OnTimedEvent(Object source, ElapsedEventArgs e) in
 c:\Users\user\Documents\Visual Studio 2012\Projects\test_tcp_manager\test_tcp_ma
nager\Program.cs:line 52

错误不规律地发生一秒钟或几秒钟。我想知道为什么,我想知道如何解决这个问题。

U**PDATE 来自用户输入的 FIX** 来自用户用户反馈的第一个代码修复:

tcp_client 代码现在如下所示:

 class Program
{
    const int ourPort = 9090;
    static IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("172.22.1.22"), 3000);
    static ASCIIEncoding encoder = new ASCIIEncoding();
    static void Main(string[] args)
    {
        while (true)
        {
            try
            {
                using( TcpClient client = new TcpClient())
                {
                    client.Connect(serverEndPoint);
                    NetworkStream clientStream = client.GetStream();

                    byte[] buffer = encoder.GetBytes("Hello Server!");

                    clientStream.Write(buffer, 0, buffer.Length);

                    client.Close();
                }
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee.ToString());
            }
        }
    }
}

tcp_server 代码现在如下所示:

class Server
{
    private static TcpListener tcpListener;
    static int count = 0;
    public Server()
    {
        //
    }

    static void Main(string[] args)
    {
        tcpListener = new TcpListener(IPAddress.Any, 3000);
        tcpListener.Start();
        while (true)
        {
            TcpClient client = tcpListener.AcceptTcpClient();
            NetworkStream clientStream = client.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            bytesRead = 0;

            try
            {
                bytesRead = clientStream.Read(message, 0, 4096);
            }
            catch (Exception ee)
            {
                Console.WriteLine("Socket rror");
                Console.WriteLine(ee.ToString());
            }
            count++;

            ASCIIEncoding encoder = new ASCIIEncoding();
            Console.WriteLine(count + " " + encoder.GetString(message, 0, bytesRead));
        }
    }
}

【问题讨论】:

    标签: c# tcp tcpclient tcplistener


    【解决方案1】:
    1. 发送消息后不要忘记关闭客户端。在 GC 决定将其关闭之前,该连接将一直存在。
    2. 刷新网络流没有任何作用。不要迷信并冲洗一切,因为它看起来更安全。
    3. 您正在接受计时器。我以前从未见过这种错误。你为什么这样做?您应该在一个循环中接受所有连接的客户端,并独立地为它们服务。你为什么要在每个计时器滴答声中将服务器限制为一个客户端?
    4. 移除休眠。每当您认为自己需要睡觉时,请多想想。
    5. 您假设您将在第一次阅读时阅读“消息”。读取至少返回一个字节。它不保证其他任何事情。 TCP 没有消息。确保您的代码可以按字节处理接收传入数据。
    6. 对所有一次性资源使用 using 语句,摆脱所有尴尬的关闭调用。

    很多问题。套接字编程很难。要非常小心。

    【讨论】:

    • @usr 我更新了上面的代码,和你的建议相符吗?
    • 进步很大! (5) 仍未解决。这是一个潜在的错误,您只是不会注意到较小的消息大小。完成客户端服务后,您还需要在服务器上关闭 client
    • 如何修复 5?我不明白那部分。我会使用更大的缓冲区吗?
    • @user3573417 首先,了解为什么您的代码有错误。如果操作系统选择以单字节块的形式向您提供数据会发生什么?这是合法行为,它会导致您的应用程序以错误的方式运行(您同意吗?)。确保你把它钉牢。如果你不理解这个问题,套接字编程将是你的折磨。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 2020-09-06
    相关资源
    最近更新 更多