[通过c#中的套接字发送多个异步请求

问题描述 投票:0回答:1

我有ipaddress列表。我正在使用udp协议将请求异步发送到这些地址到snmp代理。这些地址上的可用snmp代理回复。当我使用这些地址调用BeginSendTo时,设备将以随机顺序进行回复。调用ReceiveBeginReceiveFrom并构造stateobject对象时。 T RemoteIPEndPoint不属于所答复的计算机,而是属于其他计算机。我调用BeginSendTo的方法是否正确?如果是,则y stateobject实例没有给我正确的远程端点?我正在发布我的代码。如果缺少某些内容,请更正。

public class Test
{
    Socket udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    class StateObject
    {
        public Socket Socket { get; set; }
        public byte[] DataBuff { get; set; }
        public IPEndPoint RemoteEndPoint { get; set; }
        //validation are omited
        public static StateObject Create(Socket s,byte[] dataBuf,IPEndPoint endpoint)
        {
            return new StateObject() { Socket = s, DataBuff = dataBuf, RemoteEndPoint = endpoint };
        }

        public static StateObject Transform(object objectstate)
        {
            return objectstate as StateObject;
        }
    }
    public void Fx()
    {
        //list of ip address from 190.188.191.1 - 190.188.191.100
        var address = new[] {
            IPAddress.Parse("190.188.191.1"),
            IPAddress.Parse("190.188.191.100")
        };

        byte[] dataGram = new byte[1024];
        foreach (IPAddress item in address)
        {
            udpSocket.BeginSendTo(dataGram,
                        0,
                        dataGram.Length,
                        SocketFlags.None,
                        new IPEndPoint(item, 161),
                        SendComplete,
                        StateObject.Create(udpSocket, null, new IPEndPoint(item, 161))
                        );
        }
    }

    private void SendComplete(IAsyncResult ar)
    {
        StateObject obj = StateObject.Transform(ar.AsyncState);
        obj.Socket.EndSendTo(ar);//ignore the no of bytes send for now
        byte[] receivedBytes = new byte[1024 * 4];//assume 4kb is enough for response
        var ep = obj.RemoteEndPoint as EndPoint;
        obj.Socket.BeginReceiveFrom(receivedBytes,
            0,
            receivedBytes.Length,
            SocketFlags.None,
            ref ep,
            ReceivedData,
            StateObject.Create(obj.Socket, receivedBytes, obj.RemoteEndPoint)
            );
    }

    private void ReceivedData(IAsyncResult ar)
    {
        StateObject obj = StateObject.Transform(ar.AsyncState);
        var ep = obj.RemoteEndPoint as EndPoint;

        //response received from ip 190.188.191.2 but in stateobject.remoteendpoint will give 190.188.191.1

        var bytesReceived  = obj.Socket.EndReceiveFrom(ar,ref ep);
        byte[] data = new byte[bytesReceived];
        Array.Copy(obj.DataBuff,data, bytesReceived);
    }
}
c# sockets udp endpoint
1个回答
0
投票

最后,我想出了解决多个udp请求的方法。在状态类型中引入的新字段称为“ ID”。生成ip地址时,会生成一个唯一的标识符。该标识符分配给State Type实例并进行缓存。此ID也在请求中发送,以便识别来自特定IP地址的响应并从其缓存中检索其状态值。

    Socket udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 
      ProtocolType.Udp);

    Dictionary<int, StateObject> _Cache = new Dictionary<int, StateObject>();

    class StateObject
    {
        public int ID { get; set; }//uniquely identify the response

        public Socket Socket { get; set; }
        public byte[] DataBuff { get; set; }
        public IPEndPoint RemoteEndPoint { get; set; }
        //validation are omited
        public static StateObject Create(Socket s, byte[] dataBuf, IPEndPoint endpoint)
        {
            return new StateObject() { Socket = s, DataBuff = dataBuf, RemoteEndPoint = endpoint };
        }

        public static StateObject Transform(object objectstate)
        {
            return objectstate as StateObject;
        }
    }

    //This function is used to generate range of address and corresponding identifiers
    IEnumerable<KeyValuePair<IPAddress, int>> GenerateMaps(IPAddress start, IPAddress end)
    {
        int count = -1;
        yield return new KeyValuePair<IPAddress, int>(start, ++count);

        //other address in the range

        yield return new KeyValuePair<IPAddress, int>(end, ++count);
    }

也不是从特定的主机BeginReceiveFrom接收,而是由能够接收和托管的BeginReceive函数代替。标识符映射有助于解决缓存中的问题。

© www.soinside.com 2019 - 2024. All rights reserved.