我使用此代码接收扫描线:
StateObject stateobj = (StateObject)ar.AsyncState;
stateobj.workSocket.BeginReceive(new System.AsyncCallback(VideoReceive), stateobj);
UdpClient client = stateobj.workSocket;
IPEndPoint ipendp = new IPEndPoint(IPAddress.Any, 0);
byte[] data = client.EndReceive(ar, ref ipendp);
BinaryReader inputStream = new BinaryReader(new MemoryStream(data));
inputStream.BaseStream.Position = 0;
int currentPart = inputStream.ReadInt32();
if (currentPart == part)
{
int a = 0;
int colum = inputStream.ReadInt32();
for (; a < packets.GetLength(1); a++)
{
packets[colum, a, 2] = inputStream.ReadByte();
packets[colum, a, 1] = inputStream.ReadByte();
packets[colum, a, 0] = inputStream.ReadByte();
}
receiverCheck++;
}
else if (currentPart != part)
{
part++;
mask2.Data = packets;
pictureBox1.BeginInvoke(new MethodInvoker(() => { pictureBox1.Image = mask2.ToBitmap(); }));
int colum = inputStream.ReadInt32();
for (int a = 0; a < packets.GetLength(1); a++)
{
packets[colum, a, 2] = inputStream.ReadByte();
packets[colum, a, 1] = inputStream.ReadByte();
packets[colum, a, 0] = inputStream.ReadByte();
}
}
收到所有扫描线后,图片框中显示的图像。
这应该可行,但即使在localhost上也有很多丢失的数据包(只有~95的480),所以我有条纹图像。我发现了类似的问题here。 回答:
private void OnReceive(object sender, SocketAsyncEventArgs e)
{
TOP:
if (e != null)
{
int length = e.BytesTransferred;
if (length > 0)
{
FireBytesReceivedFrom(Datagram, length, (IPEndPoint)e.RemoteEndPoint);
}
e.Dispose(); // could possibly reuse the args?
}
Socket s = Socket;
if (s != null && RemoteEndPoint != null)
{
e = new SocketAsyncEventArgs();
try
{
e.RemoteEndPoint = RemoteEndPoint;
e.SetBuffer(Datagram, 0, Datagram.Length); // don't allocate a new buffer every time
e.Completed += OnReceive;
// this uses the fast IO completion port stuff made available in .NET 3.5; it's supposedly better than the socket selector or the old Begin/End methods
if (!s.ReceiveFromAsync(e)) // returns synchronously if data is already there
goto TOP; // using GOTO to avoid overflowing the stack
}
catch (ObjectDisposedException)
{
// this is expected after a disconnect
e.Dispose();
Logger.Info("UDP Client Receive was disconnected.");
}
catch (Exception ex)
{
Logger.Error("Unexpected UDP Client Receive disconnect.", ex);
}
}
}
答案有方法FireBytesReceivedFrom(),但我找不到它。我该如何使用此代码?这段代码有帮助吗?
答案 0 :(得分:1)
UDP不保证将收到所有数据包,它们将以任何特定顺序到达。因此,即使你让这个“工作”意识到它可能(很可能)在某些时候失败。
当您调用BeginReceive时,您正在开始同步读取。当数据到达时,将调用您的事件处理程序,然后然后需要调用EndReceive。目前你正在立即调用EndReceive,这可能是出错的原因。
其他一些说明:
我建议您不要试图聪明并重新使用缓冲区,因为这可能会导致您在尝试读取数据时通过覆盖数据而丢失数据。从简单开始,并在它运行良好后添加这样的优化。
此外,goto可能会造成严重破坏。您似乎正在尝试使用它来重试,但此代码在数据接收事件处理程序中运行。事件处理程序应该以最轻量级的方式处理事件然后返回,而不是开始循环...特别是因为这里的循环可能导致对同一事件处理程序的重入调用。
使用异步通信,您应该开始读取并退出。当您最终收到数据(调用事件处理程序)时,抓住它并启动新的异步读取。任何比这更复杂的事情都可能导致问题。
你失踪的Fire ...方法可能只是引发(触发)一个事件来告诉客户数据已经到达。这是你应该抓住收到的数据并用它做一些事情的地方。
如果您使用示例来构建此代码,那么我建议您寻找更好的示例。 (在任何情况下,我总是建议尝试找到3个例子,这样你就可以比较实现,因为你通常会以这种方式学到很多东西)