ios - 为什么 recvfrom 方法的返回值是 4294967295 应该是 0 或 -1?

标签 ios objective-c networking udp bsd

我正在使用 sendto/recvfrom 方法在我的应用程序中发送/接收 UDP 数据包。现在我的接收方法如下:

- (void)listenForPackets
{
    int listeningSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (listeningSocket <= 0) {
        NSLog(@"Error: listenForPackets - socket() failed.");
        return;
    }

    // set timeout to 2 seconds
    struct timeval timeV;
    timeV.tv_sec = 2;
    timeV.tv_usec = 0;

    if (setsockopt(listeningSocket, SOL_SOCKET, SO_RCVTIMEO, &timeV, sizeof(timeV)) == -1) {
        NSLog(@"Error: listenForPackets - setsockopt failed");
        close(listeningSocket);
        return;
    }

    // bind the port
    struct sockaddr_in sockaddr;
    memset(&sockaddr, 0, sizeof(sockaddr));

    sockaddr.sin_len = sizeof(sockaddr);
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(18686);
    sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    int status = bind(listeningSocket, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
    if (status == -1) {
        close(listeningSocket);
        NSLog(@"Error: listenForPackets - bind() failed.");
        return;
    }

    // receive
    struct sockaddr_in receiveSockaddr;
    socklen_t receiveSockaddrLen = sizeof(receiveSockaddr);

    size_t bufSize = 9216;
    void *buf = malloc(bufSize);
    size_t result = recvfrom(listeningSocket, buf, bufSize, 0, (struct sockaddr *)&receiveSockaddr, &receiveSockaddrLen);

    NSData *data = nil;

    if (result > 0) {
        NSLog(@"reslut:%zu",result);
        if (result != bufSize) {
            buf = realloc(buf, result);
        }
        data = [NSData dataWithBytesNoCopy:buf length:result freeWhenDone:YES];

        char addrBuf[INET_ADDRSTRLEN];
        if (inet_ntop(AF_INET, &receiveSockaddr.sin_addr, addrBuf, (size_t)sizeof(addrBuf)) == NULL) {
            addrBuf[0] = '\0';
        }

        NSString *address = [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];
        NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

        dispatch_async(dispatch_get_main_queue(), ^{
            [self didReceiveMessage:msg fromAddress:address];
        });

    } else {
        free(buf);
    }

    close(listeningSocket);
}

当我点击一个按钮时,我将发送一个 UDP 广播并调用上面的方法来收听。一开始,我没有使用 setsockopt(listeningSocket, SOL_SOCKET, SO_RCVTIMEO, &timeV, sizeof(timeV)) 设置接收超时。但是多次点击会出现bind错误,可能第一个还是listen the port,没有完成。所以我添加了一个超时秒来确保前一个完成。但是,当我设置超时时,上面的结果值为 4294967295。然后导致我的应用程序崩溃。崩溃日志如下:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSConcreteData initWithBytes:length:copy:deallocator:]: absurd length: 4294967295, maximum size: 2147483648 bytes'
*** First throw call stack:
(0x2ed14e83 0x390716c7 0x2ed14dc5 0x2f64799b 0x2f63fe53 0x2f63fd4d 0x2f64dbab 0x2f64db69 0x13cffb 0x13cdb3 0x395560c3 0x3955b7d9 0x3955b9c5 0x39685dff 0x39685cc4)
libc++abi.dylib: terminating with uncaught exception of type NSException

如果设置了超时,为什么返回值为 4294967295 而不是 0 或 -1?如何解决这个问题?任何建议将不胜感激。

最佳答案

使用 ssize_t 而不是 size_t

int result = recvfrom(listeningSocket, buf, bufSize, 0, (struct sockaddr *)&receiveSockaddr, &receiveSockaddrLen);

size_t 是无符号类型,-1 将转换为 4294967295 (uint_t32)。 试试下面的代码:

uint32_t i = -1 ;
NSLog(@"%u", i) ; // you get 4294967295

方法声明如下:

ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
         struct sockaddr *restrict address, socklen_t *restrict address_len);

感谢@MartinR 的更正。

关于ios - 为什么 recvfrom 方法的返回值是 4294967295 应该是 0 或 -1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21040754/

相关文章:

ios - '"_vDSP maxvD”错误,引用自...”在实现核心图时

linux - windows 下是否有与 justniffer 等效的嗅探器?

sockets - "Connectionless, unconnected"连接

ios - 调整 UIImage 大小时内存泄漏

iphone - iPhone 和 ASP.NET WS (XML/JSON) 之间的身份验证

ios - 单击 SpriteKit 叠加标签时如何在 SceneKit 中切换场景?

ios - 如何检测并添加丢失的电话区号?

ios - coreData Fetch 中的 NSInternalInconsistencyException

ios - 处理两个应用程序 :openURL:sourceApplication:annotation

perl - 使用 Perl 进行网络编程,作者 Stein - 仍然相关吗?