【发布时间】:2019-09-01 18:13:48
【问题描述】:
这可能是一个愚蠢的问题,但请听我说完。
在我的远程服务器上,我正在运行具有以下代码的程序:
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);
}
}
【问题讨论】:
-
嗯,这里第一个明显的错误在
Receive行。它返回“接收的字节数”。但你没有存储或使用它。 没有保证它与缓冲区的大小相同。 -
感谢您的评论。我将使用 ReceiveAndUnzip() 方法的实现来更新我的帖子。
-
是的,您在该方法中正确执行此操作,但您在
Main中未正确执行此操作。// Receives header first可能完全是谎言,因为它可能只提供了一个字节。 -
@Damien_The_Unbeliever 感谢您的评论。现在,唯一连接到我的服务器的客户端始终是我的本地计算机,并且我确保始终首先发送标头。当我还在原型设计阶段时,现在没有错误处理;我了解您的担忧和错误处理将在稍后添加:-)
-
不是错误处理,而是正确性。如果您的标头包含多个字节,则不保证您可以一次性收到所有信息,即使在另一端,它是一次性发送的。 TCP 是字节流,而不是消息。如果您希望接收到整个缓冲区的字节(
GetFileSizeInBytes假设整个缓冲区是有效的),您必须执行与ReceiveAndUnzip相同的循环行为以确保您获得所有这些字节.
标签: c# .net tcpclient tcplistener