gpt4 book ai didi

objective-c - UDP 代码只接收广播的第一个响应

转载 作者:太空宇宙 更新时间:2023-11-04 01:21:58 27 4
gpt4 key购买 nike

我正在尝试与多个 SQL Server Browser 进行通信使用以下 c + objective-c 代码的服务。

+ (void) doBrowseForServers
{
// http://mbielanczuk.com/2013/07/browsing-network-for-sql-server-instances-in-c/
// used as a reference.
SOCKET sock;
int broadcast = 1;

struct timeval timeout;
timeout.tv_sec = 5; // 10 second timeout
timeout.tv_usec = 0;

if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
NSLog(@"MSSQLBrowserServiceClient failed to initialize socket.");
return;
}

// Setting socket broadcast option.
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)) == -1)
{
NSLog(@"MSSQLBrowserServiceClient failed to set broadcast option.");
return;
}

// Set a timeout so that we do not wait forever.
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) == -1)
{
NSLog(@"MSSQLBrowserServiceClient failed to set send timeout.", errno);
return;
}

// Set a timeout so that we do not wait forever.
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) == -1)
{
NSLog(@"MSSQLBrowserServiceClient failed to set receive timeout.", errno);
return;
}

if(sendBroadcast(sock, MSSQL_BROWSER_SERVICE_PORT))
{
NSString * response = [self reciveBroadcastRespondFromSocket: sock
usingPort: MSSQL_BROWSER_SERVICE_PORT];

NSDate * lastSeen = [NSDate date];

if(0 != response.length)
{
// Processing code omitted to focus on send/receive
} // End of we had responses
}
else
{
NSLog(@"MSSQLBrowserServiceClient failed to browse for servers.");
}
} // End of beginBrowseForServers

bool sendBroadcast(SOCKET sock, int port)
{
struct sockaddr_in bcastAddr;
memset(&bcastAddr, 0, sizeof(bcastAddr));
bcastAddr.sin_family = AF_INET;
bcastAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
bcastAddr.sin_port = htons(port);
char query = 0x02;
if (sendto(sock, &query, sizeof(query), 0, (struct sockaddr *)&bcastAddr, sizeof(bcastAddr)) == -1)
{
return 0;
}

return 1;
}

+ (NSString*) reciveBroadcastRespondFromSocket: (SOCKET) sock
usingPort: (int) port
{
ssize_t recvBytes = 0;
char buf[512] = {0x00};
memset(buf,'\0', 512);

NSMutableData * mutableData = [NSMutableData data];

struct sockaddr_in recvAddr;
memset(&recvAddr, 0, sizeof(recvAddr));
recvAddr.sin_family = AF_INET;
recvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
recvAddr.sin_port = htons(port);
socklen_t recvAddrLen = sizeof(recvAddr);

while ((recvBytes = recvfrom(sock, buf, sizeof(buf)-1, 0, (struct sockaddr*)&recvAddr, &recvAddrLen)) != -1)
{
[mutableData appendBytes: buf
length: recvBytes];
}

if(mutableData.length <= 3)
{
return nil;
}

char * bytes = (char*)[mutableData bytes];

// Process code removed to focus on networking bits.
// ....

return @"";
}

问题是我似乎一次只能处理一个服务器响应。如果我多次运行这段代码,我最终可能每次都从不同的服务器接收结果(每次广播一个服务器),但我的理解是我应该通过一次广播从所有服务器接收 udp 数据报。我已经尝试增加超时时间,但每次广播我仍然只能从一台服务器接收结果。

谁能指出我做错了什么?

最佳答案

我认为罪魁祸首是在 while ((recvBytes = recvfrom 循环中。我认为它因错误而终止。

UDP 广播的一个典型“错误”是WSAECONNRESET。我不完全知道那是什么意思,无法访问有关目标端口的内容。不过,这是 UDP 广播中经常发生的错误。由于此错误几乎是预料之中的,并且它与广播目标之一而不是您的代码有关,因此解决方案是忽略此特定错误并继续循环到下一个 recvfrom(您实际上“做”当您多次运行代码时会出现这种情况)。某些操作系统允许配置套接字以自动忽略 WSAECONNRESET。例如,在 Windows 上它将是 WSAIoctl(SIO_UDP_CONNRESET)

如果这对您没有帮助,请提供有关您的代码如何运行的更多信息:循环迭代次数,它是否等待超时,确切的错误结束循环。

关于objective-c - UDP 代码只接收广播的第一个响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40263390/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com