accept()在没有连接请求的情况下返回SOCKET_ERROR

时间:2019-01-15 07:21:43

标签: c windows sockets server winsock

我正在制作一个应用程序来测试TCP连接并研究网络协议。取决于用户参数,相同的应用程序是客户端还是服务器。 我正在使用Dev-Cpp 5.11在Windows 10上进行开发。

但是,当我尝试像服务器一样运行它时,出现以下错误: 调用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 :(得分:1)

函数accept的第三个参数addrlen是一个指针。它必须指向有效的内存位置。另外,它是一个输入/输出指针,即一个变量。因此,您必须创建一个变量,其值是adrIncomming变量的大小。从accept返回后,变量将具有地址的实际长度。

此代码更合适。

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

编辑:此问题和示例中的链接专用于WinSock API,因为该问题用Windows标记。套接字API的其他实现可能具有不同的功能签名。