[C] socket recv bloqué

Résolu
jaky1212 Messages postés 127 Date d'inscription   Statut Membre Dernière intervention   -  
jaky1212 Messages postés 127 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,
Je programme un client en C sous windows seven. Mon problème est le suivant :
Je me connecte à google (avec la fonction connect(); ) puis j'envoie une requête (en respectant le protocole http/1.1 ) et suite a ce la je fais un recv(); pour récupérer ce que devrais m'envoyer google... Or mon programme se bloque a la fonction recv (); surement parce qu'elle ne reçoit rien ou n'envoie rien :s Pourtant la fonction connecte m'indique que je suis connecté au serveur ... Voici un petit bout de mon code :
SOCKET s;

s = socket(PF_INET, SOCK_STREAM, 0);
SOCKADDR_IN server;

server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("209.85.229.104");
server.sin_port = htons(80);
memset(&server.sin_zero, '\0', sizeof(server.sin_zero));

if (connect(s, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR)
fprintf(stderr, "La fonction connect a echoue.\n");
else
{
char *buffer;
buffer=(char*)calloc(500,sizeof(char));
int n;
printf("ooooo\n");
send(s, "GET / HTTP/1.1\r\nHost: www.google.fr\r\n", (int)strlen("GET / HTTP/1.1\r\nHost: www.google.fr\r\n"), 0);
printf("oooooo\n");
n = recv(s, buffer, sizeof(buffer), 0); /* Lire tout au plus sizeof(buffer) - 1 octets */
printf("oooo\n");

Résultat: seul les deux premiers "oooo" s'affiche, le troisième qui est après la fonction recv n'apparait pas :s

merci
Configuration: Windows
Firefox 3.0.13

7 réponses

  1. shinkei
     
    A y est j'ai trouvé l'astuce !!!
    J'ai cherché sans relâche et j'ai trouvé ce qui n'allait pas.
    C'est juste un problème de requête HTTP.
    Il te manque un deuxième retour à la ligne pour fonctionner,
    du coup, le serveur considérait ta requête comme incomplète
    et ne daignait même pas répondre ce bougon.

    "GET / HTTP/1.1\r\nHost: www.google.fr\r\n\r\n"


    Voilà monsieur !

    De mon côté c'était encore plus vicieux car j'envoyais une bonne requête
    mais avec en plus un caractère quelconque à la fin :
    send(s, req, len+1, 0);


    Comme quoi, il faut toujours vérifier les codes que l'on copie/colle sans réfléchir...
    Voici la nouvelle version de mon code.

    #define VERBOSE
    
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #ifdef VERBOSE
    #define PRINT(c)            printf(c)
    #define WAIT_BEFORE_EXIT    system("PAUSE")
    #else
    #define PRINT(c) 
    #define WAIT_BEFORE_EXIT 
    #endif
    
    #define CLEANUP 
    
    #define ERROR_EXIT                                                  \
    {                                                                   \
        sprintf(s_out, "error %ld\n", WSAGetLastError());               \
        PRINT(s_out);                                                   \
        CLEANUP;                                                        \
        WAIT_BEFORE_EXIT;                                               \
        return EXIT_FAILURE;                                            \
    }                                                                   \
    PRINT("OK\n");
    
    static char host_name[] = "www.google.com";
    char s_out[2048];
    
    int main(int argc, char *argv[])
    {
        int result;
        WSADATA w;
        PRINT("WSAStartup: ");
        result = WSAStartup(MAKEWORD(2, 2), &w);
        if(result != 0) ERROR_EXIT;
        if(LOBYTE(w.wVersion) != 2 || HIBYTE(w.wVersion) != 2)
        {
            PRINT("Could not find a usable version of Winsock.dll\n");
            WSACleanup();
            return(EXIT_FAILURE);
        }
        
        #undef CLEANUP
        #define CLEANUP WSACleanup();
        
        struct hostent *host;
        struct in_addr addr;
        PRINT("gethostbyname: ");
        host = gethostbyname(host_name);
        if(host == NULL) ERROR_EXIT;
    	
        PRINT("host_ip: ");
        for(int i = 0; host->h_addr_list[i]; i++)
        {
            addr.s_addr = *(DWORD*) host->h_addr_list[i];
            sprintf(s_out, "%s\t", inet_ntoa(addr)); PRINT(s_out);
        }
        PRINT("\n");
    
        SOCKET s;
        PRINT("socket: ");
        s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(s == INVALID_SOCKET) ERROR_EXIT;
    
        #undef CLEANUP
        #define CLEANUP WSACleanup(); closesocket(s);
    
        sockaddr_in clientService;
        ZeroMemory(&clientService, sizeof(sockaddr_in));
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = *(DWORD*) host->h_addr_list[0];
        clientService.sin_port = htons(80);
        PRINT("connect: ");
        result = connect(s, (SOCKADDR*)&clientService, sizeof(clientService));
        if(result == SOCKET_ERROR) ERROR_EXIT;
        
        char req[1024], buffer[1024], lowbuffer[1024];
        strcpy(req, "GET / HTTP/1.1\r\n");
        strcat(req, "Host: "); strcat(req, host_name); strcat(req, "\r\n");
        strcat(req, "\r\n");
    
        size_t len = strlen(req);
        sprintf(s_out, "REQ length : %d\nREQ msg :\n%s", len, req);
        PRINT(s_out);
        
        PRINT("send: ");
        result = send(s, req, len, 0);
        if(result < len) ERROR_EXIT;
        
        do
        {
            PRINT("recv: ");
            result = recv(s, buffer, 512, 0);
            if(result < 0) ERROR_EXIT;
            if(result)
            {
                buffer[result] = 0;
                sprintf(s_out, "ANS length : %d\nANS msg :\n%s", result, buffer);
                PRINT(s_out);
                strcpy(lowbuffer, strupr(buffer));
            }
        } while(result == 512 && strstr(lowbuffer, "</html>") == NULL);
        
        
        PRINT("shutdown_both: ");
        result = shutdown(s, SD_BOTH);
        if(result == SOCKET_ERROR) ERROR_EXIT;
        
        PRINT("END\n");
    
        CLEANUP;
        WAIT_BEFORE_EXIT;
        return EXIT_SUCCESS;
    }
    
    
    3
  2. lightmax Messages postés 34 Statut Membre 3
     
    Bonjour,

    Je suis désolé, je ne pense pas pouvoir répondre à ta question, à moins que ce ne soit une erreur de codage, je verrais demain.
    Par contre, je voudrais savoir pourquoi tu mets : "buffer=(char*)calloc(500,sizeof(char)); " au lieu de éventuellement : "buffer = malloc(500 * sizeof(char))" ?
    Par ailleurs, ca c'est pour toi, mais plutôt que de mettre des "oooo" met plutôt "La commande/fonction telle marche!" voire, et là ca te sera peut-être utile, le contenu des variables utilisées : "printf("Contenu de la variable tellevar : %d/%s", tellevar);" et un "system("PAUSE");" pour que tu ai le temps de suivre :).

    Sur ce, bonne nuit et bon courage!
    1
  3. jaky1212 Messages postés 127 Date d'inscription   Statut Membre Dernière intervention   8
     
    UP
    0
  4. lightmax Messages postés 34 Statut Membre 3
     
    Up?
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. shinkei
     
    Salut,
    j'ai le même pb que toi,
    voila mon code :

    #define VERBOSE
    
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #ifdef VERBOSE
    #define PRINT(c)            printf(c)
    #define WAIT_BEFORE_EXIT    system("PAUSE")
    #else
    #define PRINT(c) 
    #define WAIT_BEFORE_EXIT 
    #endif
    
    #define CLEANUP 
    
    #define ERROR_EXIT                                                  \
    {                                                                   \
        sprintf(s_out, "error %ld\n", WSAGetLastError());               \
        PRINT(s_out);                                                   \
        CLEANUP;                                                        \
        WAIT_BEFORE_EXIT;                                               \
        return EXIT_FAILURE;                                            \
    }                                                                   \
    PRINT("OK\n");
    
    static char host_name[] = "www.google.fr";
    char s_out[2048];
    
    int main(int argc, char *argv[])
    {
        WSADATA wsaData;
        PRINT("WSAStartup: ");
        if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) ERROR_EXIT;
    	if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    	{
            PRINT("Could not find a usable version of Winsock.dll\n");
            WSACleanup();
            return(EXIT_FAILURE);
        }
        
        #undef CLEANUP
        #define CLEANUP WSACleanup();
        
    	struct hostent *host;
    	struct in_addr addr;
    	PRINT("gethostbyname: ");
    	if((host = gethostbyname(host_name)) == NULL) ERROR_EXIT;
    	
        PRINT("host_ip: ");
        for(int i = 0; host->h_addr_list[i]; i++)
        {
            addr.s_addr = *(DWORD*) host->h_addr_list[i];
            sprintf(s_out, "%s\t", inet_ntoa(addr)); PRINT(s_out);
        }
        PRINT("\n");
    
        SOCKET ConnectSocket;
        PRINT("socket: ");
        if((ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
                                                   == INVALID_SOCKET) ERROR_EXIT;
    
        #undef CLEANUP
        #define CLEANUP WSACleanup(); closesocket(ConnectSocket);
    
        sockaddr_in clientService;
        ZeroMemory(&clientService, sizeof(sockaddr_in));
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = *(DWORD*) host->h_addr_list[0];
        clientService.sin_port = htons(80);
        PRINT("connect: ");
        if(connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService))
                                                   == SOCKET_ERROR) ERROR_EXIT;
        
        int result;
        char req[1024];
        strcpy(req, "GET / HTTP/1.1\r\n");
        strcat(req, "Host: "); strcat(req, host_name); strcat(req, "\r\n");
        //strcat(req, "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR; rv:1.7.10) Gecko/20050717 Firefox/1.0.6\r\n");
        //strcat(req, "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
        //strcat(req, "Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3\r\n");
        //strcat(req, "Accept-Encoding: gzip,deflate\r\n");
        //strcat(req, "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n");
        //strcat(req, "Keep-Alive: 300\r\n");
        //strcat(req, "Connection: keep-alive\r\n");
        strcat(req, "\r\n");
    
        size_t len = strlen(req);
        sprintf(s_out, "Request length : %d\nRequest message :\n%s", len, req);
        PRINT(s_out);
        
        PRINT("send: ");
        if((result = send(ConnectSocket, req, len+1, 0)) < len) ERROR_EXIT;
        
        //PRINT("shutdown_send: ");
        //if(shutdown(ConnectSocket, SD_SEND) == SOCKET_ERROR) ERROR_EXIT;
    
        char buffer[513];
        PRINT("recv: ");
        if((result = recv(ConnectSocket, buffer, 512, 0)) <= 0) ERROR_EXIT;
    
        buffer[result] = 0;
        sprintf(s_out, "Answer length : %d\nAnswer message :\n%s", result, buffer);
        PRINT(s_out);
    
        PRINT("shutdown_both: ");
        if(shutdown(ConnectSocket, SD_BOTH) == SOCKET_ERROR) ERROR_EXIT;
        
        PRINT("END\n");
    
        CLEANUP;
        WAIT_BEFORE_EXIT;
        return EXIT_SUCCESS;
    }
    
    
    0
  7. jaky1212 Messages postés 127 Date d'inscription   Statut Membre Dernière intervention   8
     
    re,
    calloc et malloc sont les même choses l'erreur ne vient pas de ces fonctions sinon j'aurais une erreur de segmentation... la fonction recv reste bien bloquée (malgré mes printf bizar :D ) je ne sais pas trop comment faire. Vista (ou Seven) ne bloque rien par défault ?
    0
  8. jaky1212 Messages postés 127 Date d'inscription   Statut Membre Dernière intervention   8
     
    Génial ! Meci bien :D ralala les requêtes ... faut se taper la RFC encore :D
    0