【发布时间】:2012-01-10 13:12:31
【问题描述】:
我正在使用 UDP 套接字将 C++ 应用程序与 C# 应用程序通信。
在 C# -> C++ 方向上,一切似乎都运行良好,但反过来却让我发疯。
通信确实有效,但消息在 C# 应用程序中变得很晚(例如延迟 2 秒),即使它们每帧都发送(它是一个 3D 应用程序),并且接收代码每 10 毫秒执行一次。
我需要实时,所以这是一个非常痛苦的问题。您认为这可能与丢包有关吗?那他们为什么不迷路呢?
编辑:
用于同步数据的 C# 应用代码:
public void RecibeDatos()
{
if (MessageReceived && U != null && S != null)
{
MessageReceived = false;
//Console.WriteLine("listening for messages");
U.BeginReceive(ReceiveCallback, S);
}
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient u = ((UdpState)(ar.AsyncState)).U;
IPEndPoint e = ((UdpState)(ar.AsyncState)).E;
receivedBytes = u.EndReceive(ar, ref e);
//int currentProtocol = (int) numero;
//ResetSignal = reset > 0;
//Console.WriteLine("Received: " + currentProtocol);
MessageReceived = true;
}
发送数据的C++代码:
float indiceFloat[1];
indiceFloat[0] = indice_protocolo_actual;
sender->setBuffer((void *)indiceFloat, sizeof(indiceFloat));
sender->sync();
J_Enviar(发送者)类的同步方法:
void J_Enviar::sync( void )
{
if(!_initialized) init();
if( _buffer == 0L )
{
fprintf( stderr, "Broadcaster::sync() - No buffer\n" );
return;
}
#if defined (WIN32) && !defined(__CYGWIN__)
unsigned int size = sizeof( SOCKADDR_IN );
sendto( _so, (const char *)_buffer, _buffer_size, 0, (struct sockaddr *)&saddr, size );
int err = WSAGetLastError ();
if (err!=0)
fprintf( stderr, "Broadcaster::sync() - error %d\n",err );
#else
unsigned int size = sizeof( struct sockaddr_in );
sendto( _so, (const void *)_buffer, _buffer_size, 0, (struct sockaddr *)&saddr, size );
#endif
}
为接收 C# 端提供完整的 SocketManager 代码:
using System;
using System.Net;
using System.Net.Sockets;
namespace WpfApplication1
{
public class SocketManager
{
private static SocketManager _instance = null;
static readonly object Padlock = new object();
private IPEndPoint E;
private UdpClient U;
private UdpState S;
private byte[] receivedBytes;
public static bool MessageReceived = true;
private SocketManager()
{
}
public byte[] ReceivedBytes
{
get { return receivedBytes; }
}
public static SocketManager Instance
{
get
{
lock(Padlock)
{
return _instance ?? (_instance = new SocketManager());
}
}
}
public void CreateReceivingSocket(IPAddress a, int puerto)
{
if(E==null || (E.Address != a && E.Port != puerto))
{
E = new IPEndPoint(a, puerto);
U = new UdpClient(puerto);
S = new UdpState { E = E, U = U };
}
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient u = ((UdpState)(ar.AsyncState)).U;
IPEndPoint e = ((UdpState)(ar.AsyncState)).E;
receivedBytes = u.EndReceive(ar, ref e);
//int currentProtocol = (int) numero;
//ResetSignal = reset > 0;
//Console.WriteLine("Received: " + currentProtocol);
MessageReceived = true;
}
public void RecibeDatos()
{
if (MessageReceived && U != null && S != null)
{
MessageReceived = false;
//Console.WriteLine("listening for messages");
U.BeginReceive(ReceiveCallback, S);
}
}
public void CloseConnection()
{
if (E != null)
{
E.Port = 5502;
E = null;
}
if (U != null)
U.Close();
}
}
public class UdpState
{
public IPEndPoint E;
public UdpClient U;
}
}
这是我的 dispatchertimerclick,它使程序每 10 毫秒接收一次:
_dispatcherTimer.Tick += DispatcherTimerTick;
_dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
_dispatcherTimer.Start();
private void DispatcherTimerTick(object sender, EventArgs e)
{
_exp1Class.sendData();
_sm.RecibeDatos();
byte[] recibidos = _sm.ReceivedBytes;
if (recibidos != null)
{
float numero = BitConverter.ToSingle(recibidos, 0);
_exp1Class.CurrentProtocol = (int) numero;
}
}
【问题讨论】:
-
你做错了什么,你没有提供任何细节/代码来找出问题可能与什么有关。
-
使用Wireshark 之类的程序检查原始包。这将帮助您确定实际延迟可能在哪里。
-
您能否提供用于在 C# 端接收的代码?您还可以从运行 Wireshark 跟踪中受益,以证明数据包级别发生了什么。
-
已编辑以提供代码。希望这就足够了,如果不是,我可以发布更多代码。现在将检查 Wireshank :)
-
好的,Wireshark 证明数据正在正确发送,没有延迟。是接收端工作不正常,那么……
标签: c# c++ windows sockets udp