首页 > 解决方案 > 在 Objective-C 中读取套接字数据时崩溃 - recv()

问题描述

我正在尝试从套接字读取数据,并且大部分时间都可以正常工作。

当我运行应用程序更长的时间 - 应用程序崩溃和 crashlytics 将崩溃指向 readingSocket() - 这个函数只是从套接字读取原始数据。

下面是readingSocket()的代码

-(bool) readingSocket:(NSMutableData*)dataIn readBytes:(ssize_t)quantity error:(NSError **)error {

    ssize_t readBytesNow = 0;
    ssize_t grossRead= 0;

    [dataIn setLength:0];
    if (error != nil) {
        *error = nil;
    }

    char *buffer = new char[6144];

do {
    ssize_t readBytes = (quantity - grossRead);
    readBytesNow = recv((int)raw_Socket, buffer, readBytes , MSG_DONTWAIT);

    if (readBytesNow == 0) {
            NSLog(@" read error");

            delete[] buffer;
            return false;
    }
    Else if (bytesRead < 0) {
            if (errno == EAGAIN) {

                [NSThread sleepForTimeInterval:0.5f];
                 NSLog(@" EAGAIN error");

                continue;
            }
            else {
                // if error != nil
                delete[] buffer;
                return false;
            }
     }
     else if (readBytesNow > 0) {

          grossRead += readBytesNow;
           // doing some operations

    }

} while (grossRead < quantity);



delete[] buffer;
return true;

}

阅读后我已经做了很多检查,但不确定崩溃或异常的可能原因在哪里?

在我的上述代码中处理异常的任何其他更好的方法?

标签: iossocketsexceptioncrashrecv

解决方案


如果没有 50 名声望(这里是新用户),我无法发表评论,所以我的评论作为答案。

警告:我不知道你的代码是用什么语言编写的,但我是在利用我作为 C++ 程序员的直觉(可能是平庸的程序员)。

我注意到的第一件事是这段代码:

if (error != nil) {
    *error = nil;
}

在 C 世界中,这类似于检查指针是否为空,但随后将空分配为其值。

第二件事要注意的是这个结构:

-(bool) readingSocket:(NSMutableData*)dataIn readBytes:(ssize_t)quantity error:(NSError **)error {
...
char *buffer = new char[6144];
...
ssize_t readBytes = (quantity - grossRead);

当数量 > 6144 时,即在蓝月亮中出现一次,您的网络堆栈可能会读取超过 6144 字节,这将导致缓冲区溢出。

切线评论:

1)我认为您应该注意 EAGAIN 和 EWOULDBLOCK 可能是相同的值,但不能保证。如果您不确定您的平台是否完全按照您的想法运行,您可以考虑同时检查它们。

Linux 文档的示例链接

2)你的逻辑,

if (readBytesNow == 0) {
...
} Else if (bytesRead < 0) {
...
} else if (readBytesNow > 0) {
...
}

虽然很冗长,但没有必要。您可以使用

if (readBytesNow == 0) {
...
} Else if (bytesRead < 0) {
...
} else {
...
}

以确保您没有得到额外的比较。无论如何,这种比较可能会得到优化,但这样写更有意义。我不得不再次查看“如果我错过了什么”。

希望这些帮助。


推荐阅读