gpt4 book ai didi

.net - 为什么我的客户端套接字没有收到我的服务器套接字发送的内容?

转载 作者:行者123 更新时间:2023-12-03 11:52:04 40 4
gpt4 key购买 nike

使用阻塞流式传输 .NET socket我正在连接到服务器。每当我读取少量数据时,一切顺利,数据被接收到我的缓冲区中:

using (var socket = new Socket(SocketType.Stream, ProtocolType.IP))
{
socket.Connect(IPAddress.Parse("127.0.0.1"), 5000);

byte[] buffer = new byte[BufferSize];

socket.Receive(buffer);

// Here buffer doesn't always contain all data the server sent me?
Console.WriteLine(Encoding.Default.GetString(buffer));
}

但在某些情况下,我没有收到服务器发送给我的所有内容。数据似乎被切断了。这可能是什么原因?

最佳答案

这是documented in the Receive() method ,强调我的:

The Receive method reads data into the buffer parameter and returns the number of bytes successfully read. You can call Receive from both connection-oriented and connectionless sockets.



忽略返回值时,您将不知道缓冲区的哪一部分实际包含相关数据。根据所使用的协议(protocol),您可能会或可能不会提前知道内容长度。一些协议(protocol)提供此长度,其他协议(protocol)在完成后关闭连接,还有一些协议(protocol)可以使用消息边界。

您必须将接收到的数据保存在另一个缓冲区中,并在没有更多数据可用或预期时返回或输出整个消息缓冲区。这可以这样做:
int BufferSize = 1024;

using (var socket = new Socket(SocketType.Stream, ProtocolType.IP))
{
socket.Connect(IPAddress.Parse("127.0.0.1"), 5000);

byte[] buffer = new byte[BufferSize];
string message = "";

int bytesReceived;
do
{
bytesReceived = socket.Receive(buffer);
message += Encoding.ASCII.GetString(buffer, 0, bytesReceived);

} while (bytesReceived > 0);

Console.WriteLine(message);
}

接收到的字节是 ASCII 字符(在组成的协议(protocol)中定义),因此接收到的每个字节都表示一个字符(您不能转换部分接收到的多字节 unicode 字符)。字节被转换为字符串并附加到 message多变的。代码循环直到服务器关闭连接。

同样,当事先知道消息大小时,根据所使用的协议(protocol),您可以创建一个消息缓冲区并将数据复制到每个 Receive() 上。 :
// Received using another Receive() call
int messageSize = 1234;
int totalBytesReceived = 0;
byte[] messageBuffer = new byte[messageSize];

byte[] buffer = new byte[BufferSize];

int bytesReceived;
do
{
bytesReceived = socket.Receive(buffer);

// Copy the receive buffer into the message buffer, appending after
// previously received data (totalBytesReceived).
Buffer.BlockCopy(buffer, 0, messageBuffer, totalBytesReceived, bytesReceived);
totalBytesReceived += bytesReceived;

} while (bytesReceived > 0);

// This assumes the connection wasn't closed prematurely.
Console.WriteLine(Encoding.ASCII.GetString(messageBuffer));

这又可以放在一个可重复使用的方法中:
public byte[] ReceiveMessage(Socket socket, int messageSize)
{
byte[] messageBuffer = new byte[messageSize];

int bytesReceived = 0;
int totalBytesReceived = 0;
do
{
byte[] buffer = new byte[BufferSize];

// Receive at most the requested number of bytes, or the amount the
// buffer can hold, whichever is smaller.
int toReceive = Math.Min(messageSize - totalBytesReceived, BufferSize);
bytesReceived = socket.Receive(buffer, toReceive, SocketFlags.None);

// Copy the receive buffer into the message buffer, appending after
// previously received data (totalBytesReceived).
Buffer.BlockCopy(buffer, 0, messageBuffer, totalBytesReceived, bytesReceived);

totalBytesReceived += bytesReceived;

} while (bytesReceived > 0);

if (totalBytesReceived < messageSize)
{
throw new Exception("Server closed connection prematurely");
}

return messageBuffer;
}

NetworkStream 它包裹了一个套接字,但它 has the same reading issues作为套接字本身。您必须监控返回值并继续调用 Read()直到您收到所有字节。 TcpClient that has a GetStream() method 也是如此,您还将在其返回值上 have to continue reading until you've read all data .

关于.net - 为什么我的客户端套接字没有收到我的服务器套接字发送的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23713664/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com