socket () возвращает -1, но ошибается 0 - PullRequest
2 голосов
/ 01 ноября 2011

Я пытался создать UDP-сокет на mingw, но socket() возвращает -1, с errno = 0.Странный.Я включил winsock2.h.Изначально у меня была ошибка компиляции undefined reference to socket@12, после установки -lws2_32 и -lwsock32 в настройках компоновщика Code :: Block, успешная компиляция.

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: ошибки нет, ошибка 0Возможно ли, что mingw не поддерживает errno ??

Ответы [ 4 ]

7 голосов
/ 01 ноября 2011

первая вещь, которую я бы сделал, это:

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;
}
5 голосов
/ 05 ноября 2011

Поскольку вы работаете с сокетами Windows, вам необходимо использовать функцию WSAGetLastError () для проверки кода ошибки.Функции сокетов Windows не устанавливают errno, поэтому вы видите errno со значением 0.

На этой старой вики-странице MinGW есть список различий между сокетами UNIX и Windows, в которых упоминается errno vs WSAGetLastError () разница в пункте 5: http://oldwiki.mingw.org/index.php/sockets

3 голосов
/ 01 ноября 2011

Функция / макрос RDF_LOG, вероятно, вызывает какую-то другую функцию в библиотеке времени выполнения C, которая сбрасывает errno в 0. Вам необходимо захватить значение errno сразу после сбоя socket, чтобы это произошлочтобы быть точным.

0 голосов
/ 22 июля 2015

Не видел, что упоминалось в другом ответе, но есть другая проблема с кодом выше. Дескрипторы сокетов Winsock имеют тип SOCKET, который в моем MinGW winsock2.h определен как unsigned int.

Если вы предполагаете, что сокеты Winsock имеют тип int, такой как дескрипторы файлов Unix, проверка состояния возврата отрицательной ошибки может привести к ложному сообщению об ошибке, поскольку Winsock не гарантирует, что значение дескриптора сокета будет сопоставлено с целочисленным положительным знаком. ,

Функции Winsock, которые возвращают дескриптор сокета (socket (), accept () и т. Д.), Вместо этого возвращают SOCKET_INVALID при ошибке, которая определяется как (SOCKET) ~ 0. Как упомянуто выше, вы должны затем использовать WSAGetLastError (), чтобы получить номер системной ошибки.

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

...