环回中的 WinSock UDP 套接字创建顺序。

Posted

技术标签:

【中文标题】环回中的 WinSock UDP 套接字创建顺序。【英文标题】:WinSock UDP socket creation order in loopback. 【发布时间】:2013-01-16 15:52:48 【问题描述】:

我有一个用于专用 LAN 的网络应用程序。我正在使用环回进行测试。当我在 LAN 上测试时,套接字创建顺序无关紧要。如果我使用环回 127.0.0.1 进行测试,则存在套接字创建排序问题。为什么在回送时会有所不同?

这里有更多细节......

有一台服务器和许多客户端实例。服务器通过 UDP 广播数据。客户端接收数据并处理它。

我需要让网络层不关心服务器或客户端的启动顺序。我的案例很难管理流程创建。应用程序实例应该能够以任何顺序在网络上启动,并且在发送数据时只看到在 UDP 端口上广播的数据。

但是我设置 UDP 套接字的方式有一些东西会强制进行订购。我必须启动客户端,然后启动服务器。如果我在服务器进行 UDP 广播之后启动客户端,则客户端套接字不会接收数据。如果我强制正在运行的服务器实例拆除并重建其 UDP 套接字,突然间所有客户端都开始接收数据。

我创建套接字的方式一定有问题。客户端和服务器代码使用共享函数库来创建 UDP 套接字。所以服务器在 m_fdOut 上发送。客户端的每个实例都在 m_fdIn 上接收。

我在这里做错了什么?

SOCKET m_fdIn;
SOCKET m_fdOut;

if ((m_fdIn = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)

    WARNF("socket failed, winsock error %d\n", WSAGetLastError());
    exit(1);


if ((m_fdOut = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)

    WARNF("socket failed, winsock error %d\n", WSAGetLastError());
    exit(1);



int sockopt = 1;
if (setsockopt(m_fdOut, SOL_SOCKET, SO_BROADCAST, (char *)&sockopt,
     sizeof(sockopt)) < 0)

    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
    exit(1);


sockopt = readPreference<int>("SOL_RCVBUF", 512*1024);
if (setsockopt(m_fdIn, SOL_SOCKET, SO_RCVBUF, (char *)&sockopt, sizeof(sockopt)) < 0)

    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
    exit(1);


sockopt = 1;
if (setsockopt(m_fdIn, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)) < 0)

    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
    exit(1);


sockopt = readPreference<int>("IP_MULTICAST_TTL", 32);
if (setsockopt(m_fdOut, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&sockopt, sizeof(sockopt)) < 0)

    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError());
    exit(1);


String destAdd = "255.255.255.255"
int portNumber = 1234;
int n1, n2, n3 ,n4;
if (sscanf(destAddr, "%d.%d.%d.%d", &n1, &n2, &n3, &n4) != 4)

    n1 = n2 = n3 = n4 = 255;


u_long bcastAddr = (n1<<24) | (n2<<16) | (n3<<8) | n4;
outAddr.sin_family = AF_INET;
outAddr.sin_port = htons(portNumber);
outAddr.sin_addr.s_addr = htonl(bcastAddr);

struct sockaddr_in in_name;
in_name.sin_family = AF_INET;
in_name.sin_addr.s_addr = INADDR_ANY;
in_name.sin_port = htons(portNumber);

if (bind(m_fdIn, (struct sockaddr *)&in_name, sizeof(in_name)) < 0)

    WARNF("bind failed, winsock error %d\n", WSAGetLastError());
    exit(1);

【问题讨论】:

这里我不会阅读整个代码,而是问一个概念问题:服务器定期发送到广播,是吗?或者只是一次“你好,我在这里”? 服务器正在通过广播发送一系列数据报。数据是这样的,任何客户端实例都可以在数据流的“中间”获取并开始做它的事情。 广播到 255.255.255.255 已被弃用大约 20 年。您应该使用子网定向广播。您也不需要在同一个进程中使用两个 UDP 套接字:一个就可以了。 通常我们进行子网划分。我正在发送 255 进行测试。有一些数据从客户端流回服务器。我尝试了单个套接字实现。服务器正在接收它发送的数据。由于发件人地址是我的,因此没有明显的方法可以将其过滤掉,但我明确需要处理环回。 【参考方案1】:

所以我确实将实现从 UDP 广播更改为多播。这似乎在环回中起作用,因此多个进程可以共享端口。

【讨论】:

以上是关于环回中的 WinSock UDP 套接字创建顺序。的主要内容,如果未能解决你的问题,请参考以下文章

UDP 打孔 (c++/winsock)

如何接收 Post 请求正文并将该正文传递给我在环回中的函数

Winsock编程基础2(Winsock编程流程)

扩展内置用户模型以支持环回中的更多属性和行为

如何在 Winsock 中查找当前使用的 UDP 接收缓冲区大小

winsock是啥,是一门语言还是一个文件?