這是documented in the Receive()
method,重點煤礦:
接收方法數據讀入到緩衝參數和返回的字節數成功讀取。您可以從面向連接和無連接的套接字調用接收。
當忽略返回值時,您將不知道緩衝區的哪一部分實際上包含相關數據。根據使用的協議,您可能事先或可能不知道內容的長度。一些協議提供這個長度,其他協議在完成時關閉連接,而另一些協議可以使用消息邊界。
您必須將接收到的數據保存在另一個緩衝區中,並在沒有更多數據可用或預期時返回或輸出整個消息緩衝區。這可以這樣來完成:
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字符(如在虛構的協議中定義),因此接收到的每個字節表示一個字符(不能轉換部分地接收多字節Unicode字符) 。字節被轉換爲字符串並附加到message
變量。代碼循環直到服務器關閉連接。
當消息大小是在事先已知的,再次,這取決於所使用的協議,則可以創建一個消息緩衝器和那裏複製每個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。
這意味着作爲一個參考問題來關閉看起來相似的重複問題。請評論或提出改進建議,或者選擇其他答案。 – CodeCaster