这可能是一个愚蠢的问题,但是请听我说。
在我的远程服务器上,我正在运行一个包含以下代码的程序:
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);
}
}
答案 0 :(得分:2)
您必须更改代码以循环接受新客户端。如果您希望与客户端连接,则可能要使用Receive和Accept的一些异步版本,并在循环中生成一些任务来处理客户端-这虽然不是最佳方法,但是应该可以。
网络编程是一个棘手的问题。这里有一些提示。
您不能保证客户端中的单个发送调用将导致服务器上的单个接收。您的消息可以分为片段,或者如果您快速发送几条消息,它们也可以全部合并在一起,并通过一个接收呼叫来接收。
该问题的一种解决方案是在邮件的开头加上标题,例如具有4个字节的整数。这个整数是您的邮件标题,仅包含有关您的邮件有多长时间(以字节为单位)的信息。
您要执行的操作是接收,直到获得此4字节整数标头,然后接收其余消息为止-现在,您知道消息有多长,因此您可以接收到直到收到完整消息为止。对每条新消息重复此过程。
这称为碎片整理或碎片整理。有多种实现方法:定界符,以固定大小的标头为前缀的消息,以及两者之间的某些混合。
在tcp中,半打开和半关闭连接存在问题。简而言之,这仅意味着您无法确定连接是否仍有效-如果您不交换任何消息,则对等/客户端已连接。当对等/客户端断开连接时,您的接收呼叫应返回0-这意味着连接已关闭,但TCP的工作方式并非总是如此,因此您必须考虑以避免各种相关问题。
您可以实现的最简单的Keep-Alive机制只是一些超时逻辑,例如2分钟内未收到任何消息表示对等/客户端已断开连接。或添加每隔X秒发送的其他心跳消息,如果对端/客户端在一定时间内未发送,则会使对等/客户端超时。
如果您未实现任何自定义协议,并且不想自己解决某些聪明人已经解决的所有TCP问题,则搜索库。