【问题标题】:socket() return -1 but errno 0socket() 返回 -1 但 errno 0
【发布时间】:2011-11-01 04:41:51
【问题描述】:

我试图在 mingw 上创建一个 UDP 套接字,但 socket() 返回 -1,errno = 0。奇怪的。 我已经包含了winsock2.h。 最初我有编译错误undefined reference to socket@12,设置后 -lws2_32-lwsock32 到 Code::Block 的 Linker Settings,编译成功。

sockfd = socket(AF_INET, SOCK_DGRAM, 0);
RDF_LOG(kDEBUG, "sockfd %d ", sockfd);
if (sockfd < 0){
    RDF_LOG(kERROR, "ERROR: %s , errno %d\n", strerror(errno), errno);
}

结果 --> sockfd -1 错误:没有错误,errno 0


好的,我将 RDF_LOG 改为 fprintf。

int tmp = 0;

sockfd = socket(AF_INET, SOCK_DGRAM, 0);
tmp = errno;
fprintf(stderr, "sockfd %d ", sockfd);
if (sockfd < 0){
    fprintf(stderr, "socket: %s , errno %d\n", strerror(tmp), tmp);
}

返回的结果仍然是 --> sockfd -1 socket: No error , errno 0 难道mingw不支持errno??

【问题讨论】:

    标签: c sockets mingw codeblocks winsock2


    【解决方案1】:

    我要做的第一件事是这样的:

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    int tmp = errno;
    RDF_LOG(kDEBUG, "sockfd %d ", sockfd);
    if (sockfd < 0){
        RDF_LOG(kERROR, "ERROR: %s , errno %d\n", strerror(tmp), tmp);
    }
    

    我不知道RDF_LOG 可能对errno 变量做了什么,这会告诉你它是否会改变它。

    要寻找的另一件事是您已成功执行您的WSAStartup。以下最小程序有望向您展示如何做到这一点,并为调试提供一个起点:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <winsock2.h>
    
    int main (void) {
        WSADATA wsaData;
        int listenFd;
    
        if (WSAStartup(MAKEWORD(1,1), &wsaData) == SOCKET_ERROR) {
            printf ("Error initialising WSA.\n");
            return -1;
        }
    
        listenFd = socket (AF_INET, SOCK_STREAM, 0);
        if (listenFd  < 0) {
            printf ("Error %d opening socket.\n", errno);
            return -1;
        }
    
        return 0;
    }
    

    【讨论】:

    • 请注意,标准库函数不允许将errno 设置为零,最佳实践要求第三方库函数也应避免这样做。
    • @paxdiablo 是的,我没有初始化winsock!现在它在 WSAStartup 之后工作。
    【解决方案2】:

    因为您使用的是 Windows 套接字,所以您需要使用 WSAGetLastError() 函数来检查错误代码。 Windows 套接字函数不设置 errno,这就是为什么您看到 errno 的值为 0。

    这个旧的 MinGW wiki 页面列出了 UNIX 套接字和 Windows 套接字之间的差异,在第 5 项中提到了 errno 与 WSAGetLastError() 的差异: http://oldwiki.mingw.org/index.php/sockets

    【讨论】:

      【解决方案3】:

      函数/宏RDF_LOG 可能正在调用 C 运行时库中的某个其他函数,该函数将 errno 重置为 0。您需要在 socket 失败后立即捕获 errno 的值以获取它准确地说。

      【讨论】:

        【解决方案4】:

        在另一个答案中没有看到这个,但是上面的代码还有另一个问题。 Winsock 套接字描述符是 SOCKET 类型,在我的 MinGW winsock2.h 中定义为 unsigned int。

        如果您假设 Winsock 套接字是 Unix 文件描述符之类的 int 类型,则检查负错误返回状态可能会导致错误报告,因为 Winsock 不保证套接字描述符值将映射到正符号整数值.

        返回套接字描述符(socket()、accept() 等)的 Winsock 函数会在错误时返回 SOCKET_INVALID,该错误定义为 (SOCKET) ~0。如上所述,您应该使用 WSAGetLastError() 来获取系统错误号。

        https://msdn.microsoft.com/en-us/library/windows/desktop/ms740516%28v=vs.85%29.aspx

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-06
          • 2015-03-01
          • 1970-01-01
          相关资源
          最近更新 更多