accept () возвращает SOCKET_ERROR без запроса соединения - PullRequest
0 голосов
/ 15 января 2019

Я делаю приложение для тестирования TCP-соединений и изучения сетевых протоколов. Одно и то же приложение является клиентом или сервером в зависимости от параметров пользователя. Я разрабатываю его на Windows 10, используя Dev-Cpp 5.11.

Но, когда я пытаюсь запустить его как сервер, я получаю следующую ошибку: Когда звоните accept():

  1. accept() возвращает SOCK_ERROR.
  2. WSAGetLastError() вернуть неверный адрес (до listen() возвращается NULL)
  3. Приложение немедленно возвращается, отсутствует запрос на соединение с клиентом или задерживается ожидающий запрос на соединение.

Вывод:

:: SERVER MODE
:: PORT: 2020
:: Time Limit receiving: 1000ms

:: WSA Version: 0202
:: Criando SOCKET: OK
:: SOCKET Binding: OK

:: LISTENING . . .
WSA Error: Bad address
Socket Value: -1

ERRO 0 [Bad address]
--------------------------------
Process exited after 0.1634 seconds with return value 0
Pressione qualquer tecla para continuar. . .

А вот код, вызываемый с параметрами: csock -listen 2020

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <winsock2.h>

void delay(int milisecond);
char* LastErrorDescription();

    /*****************************************************************************************
    EXEMPLO DE PARAMETRO:
    csock -h IP_v_4_Address -p Remote_Port -t 500
    csock -listen 2020
    ******************************************************************************************/

    /**************************************************
    PENDENCIAS:
    - IMPLEMENTAR IPv6
    - IMPLEMENTAR MODO SERVIDOR
    - REFAZER PARAMETROS PACKAGE (-pack)
    ***************************************************/

int main(int argc, char *argv[]) {
    struct sockaddr_in sckAddr, adrIncomming;
    char request[512] = ""; //= "GET http://www.brasil.gov.br HTTP/1.1\r\n\r\n"; //"GET /index.html HTTP/1.1\nHost: www.brasil.gov.br\n";
    char BufferIn[10240];
    WSADATA wsaDADOS;
    int retWSA;
    int retCon;
    int retSend;
    int retRecv;
    int retBind;
    int i;
    int imsg;
    int time_limit = 1000; // milisegundos aguardando recebimento de pacotes
    clock_t registrador_tempo;
    _Bool closed_connection = 0;
    _Bool serverMode = 0;
    _Bool nonpersist = 0;
    _Bool bIPv6 = 0;
    SOCKET wsocket;
    SOCKET wserver;
    WORD sckVersion = (2) << 8 | (2);   // sckVersion 2.2 -> 0000001000000010

    //printf("Quantidade de Parametros: %i", argc);
    for(i = 0; i < argc; i ++){
        if(!strcmp(argv[i], "-h")){
            printf("\n:: HOST: %s", argv[i + 1]);
            sckAddr.sin_addr.s_addr = inet_addr(argv[i + 1]);
        }
        if(!strcmp(argv[i], "-p")){
            printf("\n:: PORT: %s", argv[i + 1]);
            sckAddr.sin_port = htons(atoi(argv[i + 1]));
        }
        if(!strcmp(argv[i], "-t")){
            time_limit = atoi(argv[i + 1]);
        }
        //COMANDOS MODO SERVIDOR
        else if(!strcmp(argv[i], "-listen")){
            serverMode = 1;
            printf("\n:: SERVER MODE");
            sckAddr.sin_addr.s_addr = htonl(INADDR_ANY);
            sckAddr.sin_port = htons(atoi(argv[i + 1]));
            printf("\n:: PORT: %s", argv[i + 1]);
        }
    }
    printf("\n:: Time Limit receiving: %ims", time_limit);


    // TRABALHO COM ENDEREÇO
    sckAddr.sin_family = AF_INET; //23 == AF_INET6 para usar IPv6  
    //sckAddr.sin_port = htons(80);
    //sckAddr.sin_addr.s_addr = inet_addr("170.246.252.243");

    //Inicialização WSA Socket Application
    printf("\n\n:: WSA Version: ");
    retWSA = WSAStartup(sckVersion, &wsaDADOS);
    if (retWSA == 0) {
        printf("%04X", wsaDADOS.wVersion);

        //Cria o SOCKET
        printf("\n:: Criando SOCKET: ");
        if(serverMode){
            wserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if(wserver > 0){
                printf("OK");
                retBind = bind(wserver, (struct sockaddr*)&sckAddr, sizeof(sckAddr));
                printf("\n:: SOCKET Binding: ");
                if (retBind == 0)
                    printf("OK");
                else
                    printf("ERRO %i [%s]", WSAGetLastError(), LastErrorDescription());
            }
            else
                printf("ERRO %i [%s]", WSAGetLastError(), LastErrorDescription());
        }
        else {  //CLIENT MODE
            wsocket = socket(bIPv6 ? 23 : AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if(wsocket > 0)
                printf("OK");
            else
                printf("ERRO %i [%s]", WSAGetLastError(), LastErrorDescription());
        }

        //MODO SERVIDOR
        if(serverMode){
            printf("\n\n:: LISTENING . . .\n");
            listen(wserver, 2);
            //do {
                wsocket = accept(wserver, (struct sockaddr*)&adrIncomming, (int*)sizeof(adrIncomming));
                printf("WSA Error: %s\nSocket Value: %i\n\n", LastErrorDescription(), wsocket); //TO DEPURATE
            //} while(wsocket == SOCKET_ERROR);
            closesocket(wserver);
            if(wsocket != SOCKET_ERROR){
                printf("\n:: Conexao estabelecida com: %s", inet_ntoa(adrIncomming.sin_addr)); //Tentar obter ENDEREÇO REMOTO com getpeername
                retCon = 0;
            }
            else
                retCon = -1;
        }
        //MODO CLIENTE
        else{
        //Conecta
            printf("\n:: Conectando: ");
            retCon = connect(wsocket, (struct sockaddr *)&sckAddr, sizeof(sckAddr));
            if(retCon == 0)
                printf("OK");
            else
                printf("ERRO %i [%s]", WSAGetLastError(), LastErrorDescription());
        }

        //CONEXAO ESTABELECIDA
        if (retCon == 0) {
            // ENVIA E RECEBE
            while(strcmp(&request[0], "exIt")){
                //ENVIA PACOTE
                if (!nonpersist){
                    printf("\n\n:: ENVIAR>");

                    for(i=0;i<sizeof(request);i++)
                        request[i] = '\0';

                    fgets(&request, sizeof(request), stdin);

                    // Trata os PACOTES a serem ENVIADOS
                    for (i = 0; i < sizeof(request); i++){
                        if(request[i] == '\0'){
                            // Finaliza STRING 1 posicao antes ELIMINANDO Lf do fgets()
                            for(imsg = i - 1; imsg < sizeof(request); imsg++)
                                request[imsg] = '\0';
                            break;
                        }
                        // \n
                        else if (request[i] == '\\' && request[i + 1] == 'n'){
                            request[i] = '\n';
                            // Traz todos os caracteres para 1 posicao antes
                            for (imsg = i + 1; imsg < sizeof(request); imsg++)
                                request[imsg] = request[imsg + 1];          
                        }
                        // \r
                        else if (request[i] == '\\' && request[i + 1] == 'r'){
                            request[i] = '\r';
                            // Traz todos os caracteres para 1 posicao antes
                            for (imsg = i + 1; imsg < sizeof(request); imsg++)
                                request[imsg] = request[imsg + 1];          
                        }
                    }
                }

                //Depuracao: checar string de pacotes e ASCII da string de pacotes
                /*
                printf("\n\n%s.", &request);
                printf("\n\n.");
                for(i=0;i<sizeof(request);i++)
                    printf("%i ", request[i]);
                printf(".");
                */  

                //Envia pacotes
                if(strcmp(&request, "exIt")){
                    printf("\n:: Enviando pacotes: ");
                    if(send(wsocket, request, sizeof(request), 0) == SOCKET_ERROR){  // Erro no ENVIO
                        printf("ERRO %i [%s]", WSAGetLastError(), LastErrorDescription());
                    }
                    else  //PACOTES ENVIADOS COM EXITO
                        printf("OK");

                    delay(time_limit);
                    //RECEBE PACOTE
                    retRecv = recv(wsocket, BufferIn, sizeof(BufferIn), 0);
                    if (retRecv == 0) {
                        printf("\n\n:: %s", LastErrorDescription());
                        break;
                    }
                    else {
                        printf("\n\n:: RECEBIDO:\n");
                        printf("%s", BufferIn);
                    }
                }

                //Finaliza se for conexao nao persistente
                if(nonpersist)
                    strcpy(&request, "exIt");
            }

        }
        else {  //Erro na CONEXÃO
            printf("ERRO %i [%s]", WSAGetLastError(), LastErrorDescription());
        }

        //Fecha o SOCKET
        closesocket(wsocket);
    }
    else {  // Erro no WSAStartup
        printf("ERRO %i [%s]", WSAGetLastError(), LastErrorDescription());
    }

    // Finaliza Utilização do SOCKET
    WSACleanup();

    return 0;
}

void delay(int milisecond){
    clock_t registra_tempo = clock();
    while(clock() < registra_tempo + milisecond)
    ;
}

char* LastErrorDescription(){
    static char* ret;
    switch(WSAGetLastError()){
        case WSAEINTR:{
            ret = "Interrupted function call";
            break;
        }
        case WSAEBADF:{
            ret = "WSAEBADF";
            break;
        }
        case WSAEACCES:{
            ret = "WSAEACCES";
            break;
        }
        case WSAEFAULT:{
            ret = "Bad address";
            break;
        }
        case WSAEINVAL:{
            ret = "Invalid argument";
            break;
        }
        case WSAEMFILE:{
            ret = "Too many open files";
            break;
        }
        case WSAEWOULDBLOCK:{
            ret = "Operation would block";
            break;
        }
        case WSAEINPROGRESS:{
            ret = "Operation now in progress";
            break;
        }
        case WSAEALREADY:{
            ret = "Operation already in progress";
            break;
        }
        case WSAENOTSOCK:{
            ret = "Socket operation on non-socket";
            break;
        }
        case WSAEDESTADDRREQ:{
            ret = "Destination address required";
            break;
        }
        case WSAEMSGSIZE:{
            ret = "Message too long";
            break;
        }
        case WSAEPROTOTYPE:{
            ret = "Protocol wrong type for socket";
            break;
        }
        case WSAENOPROTOOPT:{
            ret = "Bad protocol option";
            break;
        }
        case WSAEPROTONOSUPPORT:{
            ret = "Protocol not supported";
            break;
        }
        case WSAESOCKTNOSUPPORT:{
            ret = "Socket type not supported";
            break;
        }
        case WSAEOPNOTSUPP:{
            ret = "Operation not supported";
            break;
        }
        case WSAEPFNOSUPPORT:{
            ret = "Protocol family not supported";
            break;
        }
        case WSAEAFNOSUPPORT:{
            ret = "Address family not supported by protocol family";
            break;
        }
        case WSAEADDRINUSE:{
            ret = "Address already in use";
            break;
        }
        case WSAEADDRNOTAVAIL:{
            ret = "Cannot assign requested address";
            break;
        }
        case WSAENETDOWN:{
            ret = "Network is down";
            break;
        }
        case WSAENETUNREACH:{
            ret = "Network is unreachable";
            break;
        }
        case WSAENETRESET:{
            ret = "Network dropped connection on reset";
            break;
        }
        case WSAECONNABORTED:{
            ret = "Software caused connection abort";
            break;
        }
        case WSAECONNRESET:{
            ret = "Connection reset by peer";
            break;
        }
        case WSAENOBUFS:{
            ret = "No buffer space available";
            break;
        }
        case WSAEISCONN:{
            ret = "Socket is already connected";
            break;
        }
        case WSAENOTCONN:{
            ret = "Socket is not connected";
            break;
        }
        case WSAESHUTDOWN:{
            ret = "Cannot send after socket shutdown";
            break;
        }
        case WSAETOOMANYREFS:{
            ret = "WSAETOOMANYREFS";
            break;
        }
        case WSAETIMEDOUT:{
            ret = "Connection timed out";
            break;
        }
        case WSAECONNREFUSED:{
            ret = "Connection refused";
            break;
        }
        case WSAELOOP:{
            ret = "WSAELOOP";
            break;
        }
        case WSAENAMETOOLONG:{
            ret = "WSAENAMETOOLONG";
            break;
        }
        case WSAEHOSTDOWN:{
            ret = "Host is down";
            break;
        }
        case WSAEHOSTUNREACH:{
            ret = "No route to host";
            break;
        }
        case WSAENOTEMPTY:{
            ret = "WSAENOTEMPTY";
            break;
        }
        case WSAEPROCLIM:{
            ret = "Too many processes";
            break;
        }
        case WSAEUSERS:{
            ret = "WSAEUSERS";
            break;
        }
        case WSAEDQUOT:{
            ret = "WSAEDQUOT";
            break;
        }
        case WSAESTALE:{
            ret = "WSAESTALE";
            break;
        }
        case WSAEREMOTE:{
            ret = "WSAEREMOTE";
            break;
        }
        case WSASYSNOTREADY:{
            ret = "Network subsystem is unavailable";
            break;
        }
        case WSAVERNOTSUPPORTED:{
            ret = "WINSOCK.DLL version out of range";
            break;
        }
        case WSANOTINITIALISED:{
            ret = "Successful WSAStartup() not yet performed";
            break;
        }
        case WSAEDISCON:{
            ret = "WSAEDISCON";
            break;
        }
        case WSAENOMORE:{
            ret = "WSAENOMORE";
            break;
        }
        case WSAECANCELLED:{
            ret = "WSAECANCELLED";
            break;
        }
        case WSAEINVALIDPROCTABLE:{
            ret = "WSAEINVALIDPROCTABLE";
            break;
        }
        case WSAEINVALIDPROVIDER:{
            ret = "WSAEINVALIDPROVIDER";
            break;
        }
        case WSAEPROVIDERFAILEDINIT:{
            ret = "WSAEPROVIDERFAILEDINIT";
            break;
        }
        case WSASYSCALLFAILURE:{
            ret = "WSASYSCALLFAILURE";
            break;
        }
        case WSASERVICE_NOT_FOUND:{
            ret = "WSASERVICE_NOT_FOUND";
            break;
        }
        case WSATYPE_NOT_FOUND:{
            ret = "WSATYPE_NOT_FOUND";
            break;
        }
        case WSA_E_NO_MORE:{
            ret = "WSA_E_NO_MORE";
            break;
        }
        case WSA_E_CANCELLED:{
            ret = "WSA_E_CANCELLED";
            break;
        }
        case WSAEREFUSED:{
            ret = "WSAEREFUSED";
            break;
        }
        case WSAHOST_NOT_FOUND:{
            ret = "Host not found";
            break;
        }
        case WSATRY_AGAIN:{
            ret = "Non-authoritative host not found";
            break;
        }
        case WSANO_RECOVERY:{
            ret = "This is a non-recoverable error";
            break;
        }
        case WSANO_DATA:{
            ret = "Valid name, no data record of requested type";
            break;
        }

    }

    return ret;
}

1 Ответ

0 голосов
/ 15 января 2019

Функция accept третий параметр addrlen является указателем. Он должен указывать на правильную ячейку памяти. Кроме того, это указатель на вход / выход, то есть переменная. Таким образом, вы должны создать переменную со значением, равным размеру вашей adrIncomming переменной. После возврата из accept переменная будет иметь фактическую длину адреса.

Этот код более уместен.

int adrLength = sizeof(adrIncomming);
wsocket = accept(wserver, (struct sockaddr*)&adrIncomming, &adrLength);

Редактировать: Ссылка в этом ответе и примере специфична для WinSock API, так как вопрос помечен Windows. Другие реализации API сокетов могут иметь разные сигнатуры функций.

...