使用套接字接收数据包
本文关键字:数据包 套接字 | 更新日期: 2023-09-27 18:14:31
我是套接字编程的新手,我只是想问一些问题。
我试图在客户端和服务器之间创建简单的接收方和发送方数据包(好吧,我使用同一台计算机),但我有一个问题…
发送功能正常,但我不知道如何接收与发送的数据包大小完全相同的数据包
例如,我从客户端发送5个字节到服务器,我只是想让服务器也只接收5个字节,不多也不少,我想用Socket这样做,我已经包含了短(int16 2字节)格式的数据包的大小。这里是我的发送包代码:
public static void Send(Socket socket, byte[] buffer, int timeout)
{
int startTickCount = Environment.TickCount;
int sent = 0;
int offset = 0;
int size = buffer.Length;
// Add size of packet in the begin of data packet with short (int16) format
List<byte> tmpdata = new List<byte>();
tmpdata.AddRange(BitConverter.GetBytes((short)(buffer.Length + 2)));
tmpdata.AddRange(buffer);
buffer = tmpdata.ToArray();
do
{
if (Environment.TickCount > startTickCount + timeout)
throw new Exception("Sending packet was timeout.");
try
{
sent += socket.Send(buffer, offset + sent, size - sent, SocketFlags.None);
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.WouldBlock ||
ex.SocketErrorCode == SocketError.IOPending ||
ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
{
Thread.Sleep(30);
}
else
throw ex;
}
} while (sent < size);
}
有人能帮帮我吗?
感谢Damien的修复我找到了解决方案,但我担心这会消耗内存使用,因为它循环每个字节,这里的代码:
public static byte[] Receive(Socket socket)
{
System.Net.Sockets.NetworkStream ns = new NetworkStream(socket);
int b = (byte)1;
List<byte> databuf = new List<byte>();
while ((b = ns.ReadByte()) != -1)
databuf.Add((byte)b);
return databuf.ToArray();
}
有没有更好的解决方案没有NetworkStream或更好的性能?由于
您没有显示您的接收代码,但是有一个bug可以很容易地修复:
// Add size of packet in the begin of data packet with short (int16) format
List<byte> tmpdata = new List<byte>();
tmpdata.AddRange(BitConverter.GetBytes((short)(buffer.Length + 2)));
tmpdata.AddRange(buffer);
buffer = tmpdata.ToArray();
int size = buffer.Length; //Moved from higher up, now that buffer is a different size
在接收端,你应该有类似的代码循环,直到你已经读取了2个字节,使用它来创建一个short
,它是接收的总大小,减去2(老实说,我只是避免在上面的代码中添加2,并将大小发送为大小忽略用于编码大小的实际字节),然后再次循环,直到你已经读取了整个消息。
有没有更好的解决方案没有NetworkStream或更好的性能?
NetworkStream作为Socket的高级包装器,所以你可以直接使用它做同样的事情:
var targetStream = new MemoryStream();
var buffer = new byte[receiveBufferSize];
int bytesReceived = 0;
while ((bytesReceived = socket.Receive(buffer)) > 0)
{
targetStream.Write(buffer, 0, bytesReceived);
}
当需要执行多个并发操作时,Socket
中还有SendAsync
和ReceiveAsync
方法可以很好地工作。但它们更复杂:
var receive = new SocketAsyncEventArgs();
var receiveBuffer = new byte[receiveBufferSize];
receive.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
receive.Completed += HandleReceived;
if (!socket.ReceiveAsync(receive))
{
HandleReceived(this, receive);
}