[C] socket recv bloqué [Résolu/Fermé]

Signaler
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
6 mars 2013
-
jaky1212
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
6 mars 2013
-
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

7 réponses

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
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 87008 internautes nous ont dit merci ce mois-ci

Messages postés
30
Date d'inscription
mardi 1 septembre 2009
Statut
Membre
Dernière intervention
28 septembre 2009
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!
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
6 mars 2013
5
UP
Messages postés
30
Date d'inscription
mardi 1 septembre 2009
Statut
Membre
Dernière intervention
28 septembre 2009
3
Up?
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;
}

Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
6 mars 2013
5
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 ?
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
6 mars 2013
5
Génial ! Meci bien :D ralala les requêtes ... faut se taper la RFC encore :D