如何在Windows上设置UDP源地址

时间:2013-03-27 11:42:33

标签: c++ c sockets udp winsock

似乎没有可移植的方法来设置从绑定到INADDR_ANY的套接字发送UDP数据报的源IP,但至少在Linux和FreeBSD上可以使用sendmsg()IP_PKTINFO完成( Linux)或IP_SENDSRCADDR(FreeBSD)选项。 (见this question。)

是否有在Windows上设置UDP源IP的等效选项?

2 个答案:

答案 0 :(得分:2)

来自MSDN

  

WSASendMsg功能

     

[...]

     

在类型为SOCK_DGRAMSOCK_RAW的IPv4套接字上,应用程序可以使用WSASendMsg函数指定用于发送的本地IP源地址。在WSAMSG结构中传递给WSASendMsg函数的控制数据对象之一可能包含in_pktinfo结构,用于指定用于发送的本地IPv4源地址。

这同样适用于具有in6_pktinfo结构的IPv6套接字。

对于双模插槽,重要的是不要将{IPv4}源地址指定为in6_pktinfo中的IPv4映射IPv6地址,而应指定为in_pktinfo结构中的IPv4地址。 / p>


Example

union {
    char in[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
    char in6[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo))];
} cdata;

WSAMSG msg;
memset(&msg, 0, sizeof(msg));
msg.name = &remote_sysaddr.addr.generic;
msg.namelen = remote_sysaddr.len;
msg.lpBuffers = &buf;
msg.dwBufferCount = 1;
msg.Control.buf = (char *)&cdata;
msg.Control.len = sizeof(cdata);

int sum = 0;

WSACMSGHDR *cmsg = WSA_CMSG_FIRSTHDR(&msg);

...
    memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
    cmsg->cmsg_level = IPPROTO_IP;
    cmsg->cmsg_type = IP_PKTINFO;
    cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
    struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(cmsg);
    pktinfo->ipi_addr.s_addr = local_addr->ipv4;
    sum += WSA_CMSG_SPACE(sizeof(struct in_pktinfo));
...

msg.Control.len = sum;

if (bs->WSASendMsg(bs->socket, &msg, 0, &bytes, NULL, NULL) != 0) {
    ...

答案 1 :(得分:-2)

我认为this就是它。

  

UdpClient构造函数(IPEndPoint)

     

此构造函数创建一个新的UdpClient,并将其绑定到localEP参数指定的IPEndPoint。在调用此构造函数之前,必须使用要从中发送和接收数据的IP地址和端口号创建IPEndPoint。您无需为发送和接收数据指定本地IP地址和端口号。如果不这样做,底层服务提供商将分配最合适的本地IP地址和端口号。