我试图学习在c#中使用套接字而且我有疑问,我使用的代码是这样的:
byte[] data = new byte[64];
int length = 0;
length = sock.Receive(data);
//more code...
因此,byte[]
数据填充了重新获取的数据,数组中的左侧空格填充为0,byte[]
是否已完全分配到内存中(全部为64字节)?如果是这样,有没有办法让byte[]
与实际发送的数据大小相同?
答案 0 :(得分:3)
您可以查看sock.Available
以查看已经发生的事情。(到目前为止)
byte[] data = new byte[sock.Available];
int length = sock.Receive(data);
//more code...
注意:由于您可能知道或者可能不知道网络上接下来会发生什么,因此通常首先只读取标题(带有大小信息)或者分配比所需更多的空间更有意义,并调用{{1}多次,直到达到记录结束。
注意:此代码假设您已经知道有一些数据需要接收,并且您已经等待了足够长的时间来准备好一些有用的数据。
如果您确实选择使用长度标题,.Recieve()
可以帮助您避免阅读部分标题并且必须重新组合它,这很好。 (在这种情况下,只有大型消息可能需要手动重组)
答案 1 :(得分:2)
如前所述,通常读取可能会返回更少的字节然后被告知。请参阅下面的解决方法函数,该函数确保它读取的字节数与告知的一样多 - 基本上是传递缓冲区的大小。功能来自here。
/// Reads data into a complete array, throwing an EndOfStreamException
/// if the stream runs out of data first, or if an IOException
/// naturally occurs.
/// </summary>
/// <param name="stream">The stream to read data from</param>
/// <param name="data">The array to read bytes into. The array
/// will be completely filled from the stream, so an appropriate
/// size must be given.</param>
public static void ReadWholeArray (Stream stream, byte[] data)
{
int offset=0;
int remaining = data.Length;
while (remaining > 0)
{
int read = stream.Read(data, offset, remaining);
if (read <= 0)
throw new EndOfStreamException
(String.Format("End of stream reached with {0} bytes left to read", remaining));
remaining -= read;
offset += read;
}
}
您可以先使用此方法来读取一个2字节整数,它应该代表将遵循的字节数。然后你再次阅读,但现在读取那个字节数,就像那个两个字节的整数一样。
但为了实现这一点,显然发送方首先必须发送一个两字节的整数,表示将跟随的数据长度 - 然后是数据本身。
所以基本上你首先在大小为2的字节数组上调用上面的函数(以获得数据长度),然后在字节数组上调用大小,如2字节整数所示(以获取数据)。
您可以使用它来阅读NetworkStream
。关于此主题还有一些reading。
答案 2 :(得分:1)
您只需使用Sub RunMc()
Dim a(1 To 2) As String
Dim MN As String
For i = 1 To 2 'Fill the array
a(i) = "m" & i
Next
MN = "Module1" 'the module name
For i = LBound(a) To UBound(a)
Application.Run MN & "." & a(i)
Next
End Sub
Sub m1()
Debug.Print "m1"
End Sub
Sub m2()
Debug.Print "m2"
End Sub
的返回值即可了解已到达的数据量。如果需要,可以使用Receive
缩短缓冲区,但这通常表示出现问题。
另请注意,TCP是一个字节流,不保留消息边界。