【发布时间】:2020-04-03 10:43:56
【问题描述】:
我有 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);
}
}
【问题讨论】:
-
您标记了UdpClient,但您没有使用它。相反,您使用的是底层 Socket ...您应该在单独的线程上侦听并从收到的数据包中找出发送者(还有消息的顺序和完整性)。这就是 UDP 的工作原理。它是无连接的、不可靠的并且不能维持秩序。你甚至不能假设在一个收到的数据包中消息是完整的......或者你根本不会收到答案。
-
我也强烈建议你看看 UdpClient 的 Task async API:ReceiveAsync 和 SendAsync
-
对于一个ip地址范围如何发送和接收。如何映射发送和接收?
-
嗯,首先,您对端口有限制。这将是矫枉过正。此外,您需要处理 lost 数据包。也就是说:在生产中,您迟早会发现某些请求根本没有得到响应。这可能有几个原因:远程没有收到请求,远程没有发送响应或远程发送响应但它在途中丢失了。您需要对此进行跟踪,以便您可以重新发出请求(如有必要)或停止等待该响应。否则你会发现你的软件似乎有“内存泄漏”。
-
感谢您的意见。让我探索其他可能性并尝试解决这个问题。