C+中的套接字+;和Windows下的C#无法正常工作 我使用UDP套接字来与C++应用程序通信C++应用程序。 在C>> C++方向上,一切似乎都很好,但反过来说,这是一个让我发疯的原因。

C+中的套接字+;和Windows下的C#无法正常工作 我使用UDP套接字来与C++应用程序通信C++应用程序。 在C>> C++方向上,一切似乎都很好,但反过来说,这是一个让我发疯的原因。,c#,c++,windows,sockets,udp,C#,C++,Windows,Sockets,Udp,通信确实有效,但在C#app中,消息会变得很晚(比如延迟2秒),即使它们每帧发送一次(这是一个3D应用程序),并且接收代码每10毫秒执行一次 我需要实时,所以这是一个非常痛苦的问题。你认为这可能与数据包丢失有关吗?那他们为什么不在另一个方向迷路呢 编辑: C#同步数据的应用程序代码: public void RecibeDatos() { if (MessageReceived && U != null && S != null)

通信确实有效,但在C#app中,消息会变得很晚(比如延迟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(发送方)类上的同步方法:

为接收C#end提供完整的SocketManager代码:

这是我的DispatcherMerclick,它使程序每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;
        }
    }

我不知道你什么时候开始你的第一个开始。(啊,我想这是从你的第一次计时开始的?)应该在你准备好接收数据后立即启动。其次,ReceiveCallback应该接收接收到的数据并将其放入某种队列中,然后立即再次调用BeginReceive。否则,您将延迟下一个数据帧的到达,直到前一个数据帧被消耗。最后,注意线程问题,因为线程计时器和UDP回调都将在应用程序主线程的不同线程上运行

代码能够正常工作的唯一原因是,即使在收到任何回调之前,您就已经预先初始化了MessageReceived=true。当第一个勾号出现时,对RecibeDatos的调用调用BeginReceive,因为bool被设置为true

把BeginReceive想象成“当你从网络上获得一些数据时给我回电话”。您不需要使用计时器轮询网络。(如果您的应用程序需要,您可以选择通过计时器使用这些数据,但暂时不考虑)

以下是大致步骤:

首先,在启动(或启用、运行等)时,您应该调用BeginReceive。现在,当数据到达时,您将收到一个通知

第二,当回调发生时,使用EndReceive完成数据字节的读取。该数据通常会被缓冲或以其他方式发送。然后,您应该再次调用BeginReceive(在回调中),以便在下一组数据可用时再次收到通知。它变成了一种异步循环


问题是如何处理您正在读取的数据。您可以考虑将数据放入队列中,然后让计时器从队列中弹出这些数据帧进行处理。请注意,数据可能会在两次滴答之间多次到达

有一件事你做错了,你没有提供任何细节/代码来找出问题可能与之相关。用类似的程序检查原始包。这将帮助您确定实际延迟的位置。您能否提供用于在C端接收的代码?此外,运行Wireshark跟踪以证明在数据包级别发生了什么也会让您受益匪浅。编辑以提供代码。希望这足够了,如果不是的话,我可以发布更多的代码。现在将检查Wireshank:)好的,Wireshark证明数据发送正确,没有延迟。这是接收端工作不正常,然后…我在每个计时器计时时调用函数RecibeDatos()。你的意思是我应该打电话给BeginReceive从回拨本身开始?@kelmer你需要更多的澄清吗?对不起,我已经出城几天了!谢谢你的回答。当你说队列时,你的意思是使用堆栈或其他东西来存储数据,然后严格按顺序弹出它们,例如?这不会使程序与发送的数据失去同步吗?嗯,队列是FIFO(先进先出),这意味着您将按顺序处理它们。如果可以在回调中足够快地处理UDP数据,则不需要使用队列。如果您进一步详细说明您尝试使用的“协议”,可能会有所帮助。您应该知道UDP是“不可靠的”,所以希望您考虑到一些可能丢失、无序或重复。
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;
}
}
        _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;
        }
    }