Les Allergies
Alimentaires
Posez votre question Signaler

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

jaky1212 104Messages postés 25 août 2009Date d'inscription 16 janvier 2012Dernière intervention - Dernière réponse le 16 sept. 2009 à 21:30
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
Lire la suite 

[C] socket recv bloqué »

7 réponses
Réponse
+2
moins plus
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;
}

Ajouter un commentaire
Réponse
+1
moins plus
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!
Ajouter un commentaire
Réponse
+0
moins plus
UP
Ajouter un commentaire
Réponse
+0
moins plus
Up?
Ajouter un commentaire
Réponse
+0
moins plus
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;
}

Ajouter un commentaire
Réponse
+0
moins plus
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 ?
Ajouter un commentaire
Réponse
+0
moins plus
Génial ! Meci bien :D ralala les requêtes ... faut se taper la RFC encore :D
Ajouter un commentaire
Ce document intitulé « [C] socket recv bloqué » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Dossier à la une
Passage au tout numérique : quel coût pour les particuliers ?