【问题标题】:Howto set the UDP source address on Windows如何在 Windows 上设置 UDP 源地址
【发布时间】:2013-03-17 11:34:35
【问题描述】:

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

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

【问题讨论】:

  • WSASendMsg 在 Windows 上是等效的。
  • WSASendMsg 会理解相同的 IP_PKTINFO 以将源 IP 设置为 Linux 吗?
  • @dtb 你想知道如何在CC# 中进行操作,这取决于语言。
  • @ScottChamberlain:是的,C 和 C# 的代码会有所不同。但这个问题与语言无关。它主要是关于Windows。如果你可以在 C 中完成,那么你可以在 C# 中完成。
  • 我现在正在运行 WSASendMsg 函数。 WSACMSGHDR.cmsg_len 的类型是 SIZE_T,而不是文档中所说的 UINT。现在我需要第二个 IP 地址进行测试...

标签: c++ c sockets udp winsock


【解决方案1】:

我认为是this

UdpClient 构造函数(IPEndPoint)

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

【讨论】:

  • -1。这没有回答套接字绑定到 IPAddress.Any 时如何设置源地址的问题
【解决方案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 地址。


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    相关资源
    最近更新 更多