保持TCP连接活动

问题描述 投票:0回答:1

这可能是一个愚蠢的问题,但请听我说。

在我的远程服务器上,我运行的程序包含以下代码:

private const int BufferSize = 1024;
private static readonly byte[] BytesBeingReceived = new byte[BufferSize];

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

    clientSocket = tcpListener.AcceptSocket();
    clientSocket.Receive(BytesBeingReceived); // Receives header first

    ReceiveAndUnzip(GetZippedFolderSizeInBytes()); 
    // GetZippedFolderSizeInBytes() reads the header, which contains information about the folder size

    Console.WriteLine("Press any key to exit the program.");
    Console.ReadLine();
}

正如所料,程序一旦连接到客户端套接字就会退出,并从客户端接收所有数据(到目前为止,客户端始终是我的本地机器)。

但是,我希望在服务器可用的情况下保持程序运行(即不重启,休眠,关闭等)。在收到客户端的所有数据后,我想保持TcpListener处于活动状态并等待可能的更多数据。如果客户端断开连接,TcpListener应该仍然保持活动状态并等待将来的挂起连接。

关于我怎么做的任何建议?

更新:

这是GetZippedFolderSizeInBytes()的实现:

private static int GetFileSizeInBytes()
{
    return Convert.ToInt32(Encoding.ASCII.GetString(BytesBeingReceived)
                                         .Replace("\0", Empty)
                                         .Split(new[] { Environment.NewLine, ":" }, StringSplitOptions.RemoveEmptyEntries)[1]);
}

以下是ReceiveAndUnzip(int numBytesExpectedToReceive)方法的实现:

private static void ReceiveAndUnzip(int numBytesExpectedToReceive)
{
    int numBytesLeftToReceive = numBytesExpectedToReceive;

    using (MemoryStream zippedFolderStream = new MemoryStream(new byte[numBytesExpectedToReceive]))
    {
        while (numBytesLeftToReceive > 0)
        {
            Array.Clear(BytesBeingReceived, 0, BufferSize);
            int numBytesReceived = clientSocket.Receive(BytesBeingReceived, SocketFlags.Partial);
            zippedFolderStream.Write(
                BytesBeingReceived, 
                0, 
                numBytesLeftToReceive < BufferSize ? numBytesLeftToReceive : BufferSize);
            numBytesLeftToReceive -= numBytesReceived;
        }

        zippedFolderStream.Unzip(afterReadingEachDocument: DoMoreStuff);
    }
}
c# .net tcpclient tcplistener
1个回答
2
投票

您必须更改代码以接受循环中的新客户端。你可能想要使用一些异步版本的Receive和Accept,并产生一些任务来处理客户端,如果你想要你的客户端连接 - 这不是真正的最佳方式,但它应该工作。

网络编程是一个棘手的问题。这里有一些提示。


1.消息碎片整理

您无法保证客户端中的单个发送呼叫将导致服务器上的单个接收。您的消息可以拆分成片段,或者如果您快速发送一些消息,则可以将它们连接在一起并通过单个接收呼叫接收。

该问题的一个解决方案是首先在消息前加上标题,例如: 4字节整数。此整数是您的邮件头,只包含有关邮件有多长的信息(以字节为单位)。

你想要做的就是接收,直到你得到这个4字节的整数标题,然后接收剩下的信息 - 你现在知道消息是多长时间,所以你收到消息直到你收到整个消息。对每个新邮件重复此过程。

这称为碎片整理或解帧。有多种方法可以实现:分隔符,前缀为固定大小标题的消息,以及这两者之间的一些混合。

2.保持活动/心跳机制

在tcp中,半开和半闭连接存在问题。简而言之,它只是意味着您无法确定连接是否仍然存在 - 如果您不交换任何消息,则连接对等/客户端。当对等/客户端断开连接时,您的接收呼叫应该返回0 - 这意味着连接已关闭,但TCP的工作方式并非总是如此,您必须考虑到这一点以避免各种相关问题。

您可以实现的最简单的Keep-Alive机制只是一些超时逻辑,例如2分钟内未收到任何消息表示对等/客户端已断开连接。或者每隔X秒添加一次心跳消息,如果在某个时间范围内没有发送,则超时对等/客户端。

3.使用一些经过良好测试的库

如果您没有实现任何自定义协议,并且不想自己解决所有已经由一些聪明人解决的TCP问题,那么搜索一个库。

© www.soinside.com 2019 - 2024. All rights reserved.