[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 -
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
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
-
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; } -
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! -
-
-
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question -
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; } -
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 ? -
Génial ! Meci bien :D ralala les requêtes ... faut se taper la RFC encore :D