2013-03-27 4 views
2

Кажется, нет никакого переносного способа установить исходный IP-адрес для отправки датаграмм UDP из сокетов, привязанных к INADDR_ANY, но по крайней мере на Linux и FreeBSD это можно сделать с помощью sendmsg() и IP_PKTINFO (Linux) или IP_SENDSRCADDR (FreeBSD). (См. this question.)Как установить адрес источника UDP в Windows

Есть ли эквивалентная опция для установки IP-адреса источника UDP в Windows?

+0

[WSASendMsg] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms741692 (v = vs.85). aspx) является эквивалентом в Windows. –

+0

Будет ли WSASendMsg понимать тот же IP_PKTINFO, чтобы установить исходный IP как Linux? –

+1

@dtb Вы хотите знать, как это сделать в 'C' или' C# ', это зависит от языка. –

ответ

2

От MSDN:

функция WSASendMsg

[...]

На IPv4 сокет типа SOCK_DGRAM или SOCK_RAW, приложение может специфический местный IP-адрес источника для использования с функцией WSASendMsg , Один из объектов данных управления, переданных в структуре WSAMSG функции WSASendMsg, может содержать структуру in_pktinfo, используемую для указания локального адреса источника IPv4 для использования.

То же самое относится к гнезду IPv6 с структурой in6_pktinfo.

для двухрежимной розеток, очень важно, чтобы источник IPv4-адрес не определен как IPv4, IPv6-адрес отображенного в in6_pktinfo, но в качестве адреса IPv4 в in_pktinfo структуре.


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

+1 Мои исследования на эту тему показывают тот же результат. – Hans

-2

0 думаю, this.

UdpClient Конструктор (IPEndPoint)

Этот конструктор создает новый UdpClient и связывает его с IPEndPoint, заданного параметром localEP. Перед вызовом этого конструктора вы должны создать IPEndPoint, используя IP-адрес и номер порта, из которого вы собираетесь отправлять и получать данные. Вам не нужно указывать локальный IP-адрес и номер порта для отправки и получения данных. Если вы этого не сделаете, основной поставщик услуг назначит наиболее подходящий локальный IP-адрес и номер порта.

+2

-1. Это не отвечает на вопрос, как установить адрес источника, когда сокет привязан к IPAddress. Любой – dtb

+0

Вы правы; Прости. –