c++ - 如何在 Windows 上设置 UDP 源地址

标签 c++ c sockets udp winsock

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

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

最佳答案

来自 MSDN :

WSASendMsg function

[...]

On an IPv4 socket of type SOCK_DGRAM or SOCK_RAW, an application can specific the local IP source address to use for sending with the WSASendMsg function. One of the control data objects passed in the WSAMSG structure to the WSASendMsg function may contain an in_pktinfo structure used to specify the local IPv4 source address to use for sending.

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

对于双模式套接字,重要的是 IPv4 源地址不是在 in6_pktinfo 中指定为 IPv4 映射的 IPv6 地址,而是在 in_pktinfo< 中指定为 IPv4 地址结构。


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) {
    ...

关于c++ - 如何在 Windows 上设置 UDP 源地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15657974/

相关文章:

c++ - 是否应该重构包含魔数(Magic Number)的屏幕尺寸常量?

c++ - 性能损失并行

java - 在 Tomcat servlet 中创建套接字 - 权限被拒绝(连接失败)

Python BaseHTTP服务器 : How to get it to stop?

linux 套接字回调

Java服务器-客户端socket通信

C++ 程序不能完全读取大量输入。为什么?

c++ - 为什么 Mac 开发者工具将 g++ 链接到 clang,而不是 clang++?

c - 在 shmdt() 之后和 shmctl(shmid, ipc_RMID, 0) 之前访问进程中的共享内存

c - C预处理程序宏替换