2010-09-08 6 views
2

Je suis un débutant quand il s'agit de programmation de socket. J'essaie actuellement de développer un serveur Web capable de traiter les requêtes HTTP de base GET et POST à ​​partir d'un navigateur. J'utilise mon ordinateur portable en tant que serveur et le client à la fois. Donc l'idée est que je devrais être capable de taper http://127.0.0.1:PORT/ dans Firefox et mon serveur web devrait pouvoir se connecter à ce port et commencer à parler. Jusqu'à présent, le code que j'ai écrit ne semble pas fonctionner. J'utilise ConText et Cygwin pour pouvoir exécuter et exécuter le programme sous Windows. J'ai également supprimé les pare-feu du port que j'utilise. Cependant, le serveur Web ne semble pas reconnaître la connexion.Programmation de socket dans C - Webserver

Des idées pourquoi? Je joins le code que j'ai écrit jusqu'ici. Toute aide serait très grandement appréciée. Au moment où le programme ne passe pas "écoute sur le port ..". J'ai isolé la faute et il semble qu'elle soit coincée sur la déclaration que j'ai soulignée.

/* Webserver Code */ 

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <arpa/inet.h>    // for the use of inet_ntop() 
#include <netinet/in.h> 

#define PORT "1500"    // the port we will connect to 
#define BACKLOG 10     // how many pending connections the queue will hold 

void *get_in_addr(struct sockaddr *sa); 


int main (void) { 

    int sockfd, new_fd=0; 
    int status; 
    struct addrinfo hints; 
    struct addrinfo *servinfo;  
    struct sockaddr_storage their_addr; 
    char s[INET6_ADDRSTRLEN]; 
    socklen_t addr_size;    

    FILE *errors; 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC;  
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_PASSIVE;  


    errors = fopen("Errors.txt", "w"); 
     fprintf(errors,"testing...\n"); 
    if(errors == NULL){ 
     fprintf(stderr, "Cant open output file\n"); 
    } 
    if ((status = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) { 
     fprintf(errors, "getaddrinfo error: %s\n", gai_strerror(status)); 
     exit(1); 
    } 

    // make a socket 
    // socket() function returns a socket file descriptor called sockfd 
    sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, 0); 

    // bind to the port we passed in to getaddrinfo() 
    if((bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen))== -1) { 
     fprintf(errors, "Binding Failed\n"); 
     exit(1); 
    }         

    // listen on the port 
    if((listen(sockfd, BACKLOG))== -1) { 
     fprintf(errors, "Listening failed\n"); 
     exit(1); 
    } else { 
     printf("Listening on port...\n"); 
} 

    //now accept an incoming connection 
    addr_size = sizeof(their_addr); 
    **new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size)**; 
printf("new_fd = %d\n", new_fd); 
    if(new_fd == -1) { 
     fprintf(errors, "Accepting failed\n"); 
     exit(1); 
} else { 
    printf("The Accepting worked\n"); 
} 

    //Prints out the address of the connector 
    inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof(s)); 
    printf("server: got connection from %s\n", s); 
    fclose(errors); 

return 0; 
} 



// To obtain the client's information 
void *get_in_addr(struct sockaddr *sa) 
{ 
    if (sa->sa_family == AF_INET) { 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 

    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

Répondre

2

getaddrinfo() peut renvoyer plusieurs entrées, y compris les entrées IPv6. Et cela pourrait être votre problème.

N.B. la vérification d'erreur est manquante après l'appel getaddrinfo().

Si vous voulez être navigateur capable de se connecter à « 127.0.0.1:PORT », vous devez soit:

  • bind() au INADDR_LOOPBACK et le port sans aucune aide de la getaddrinfo()
  • correctement appel d'installation à getaddrinfo(), définissant ai_family à AF_INET (de sorte que vous avez seulement IPv4).

Notez que si le premier paramètre à getaddrinfo() est NULL, l'adresse de retour serait mis à INADDR_ANY/in6addr_any, ce qui signifie que votre serveur serait également accepter les connexions de l'extérieur. Pour limiter les connexions à localhost, définissez le premier paramètre sur "localhost" au lieu de NULL.


Perpétuer la pièce, ici va mon getaddrinfo() résultat Code dumper:

struct addrinfo hints, *aires=0, *ai; 
    int i; 
    int rc; 

    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = AF_INET; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_PASSIVE; 
    rc = getaddrinfo("localhost", "1500", &hints, &aires); 
    if (rc == 0) { 
     for (ai=aires, i=0; ai; ai=ai->ai_next, i++) { 
      printf("gai: ai[%d].ai_canonname = %s\n", i, ai->ai_canonname); 
      printf("gai: ai[%d].ai_flags  = %d\n", i, ai->ai_flags); 
      printf("gai: ai[%d].ai_family = %d (%s)\n", i, ai->ai_family, get_family_name(ai->ai_family)); 
      printf("gai: ai[%d].ai_socktype = %d\n", i, ai->ai_socktype); 
      printf("gai: ai[%d].ai_protocol = %d (%s)\n", i, ai->ai_protocol, get_proto_name(ai->ai_protocol)); 
      printf("gai: ai[%d].ai_addrlen = %d\n", i, (int)ai->ai_addrlen); 

      if (ai->ai_family == AF_INET) { 
       struct sockaddr_in *sa = (struct sockaddr_in *)ai->ai_addr; 
       printf("gai: ai[%d].ai_addr[IPv4].sin_family = %d (%s)\n", i, sa->sin_family, get_family_name(sa->sin_family)); 
       printf("gai: ai[%d].ai_addr[IPv4].sin_port = %d\n", i, ntohs(sa->sin_port)); 
       printf("gai: ai[%d].ai_addr[IPv4].sin_addr = %s\n", 
        i, inet_ntop(AF_INET, &sa->sin_addr, buf, sizeof(buf))); 
      } else if (ai->ai_family == AF_INET6) { 
       struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ai->ai_addr; 
       printf("gai: ai[%d].ai_addr[IPv6].sin6_family = %d (%s)\n", i, sa->sin6_family, get_family_name(sa->sin6_family)); 
       printf("gai: ai[%d].ai_addr[IPv6].sin6_port  = %d\n", i, ntohs(sa->sin6_port)); 
       printf("gai: ai[%d].ai_addr[IPv6].sin6_flowinfo = %d\n", i, sa->sin6_flowinfo); 

       printf("gai: ai[%d].ai_addr[IPv6].sin6_addr  = %s\n", 
        i, inet_ntop(AF_INET6, &sa->sin6_addr, buf, sizeof(buf))); 

       printf("gai: ai[%d].ai_addr[IPv6].sin6_scope_id = %d\n", i, sa->sin6_scope_id); 
      } else { 
       printf("gai: ai[%d].ai_addr = %p\n", i, ai->ai_addr); 
      } 
      printf("\n"); 
     } 
    } else { 
     printf("gai: failed (%d)\n", rc); 
    } 
    freeaddrinfo(aires); 
+0

Merci pour cela! J'ai fait les changements que vous avez suggérés et cela fonctionne =). Maintenant, pour faire face au problème de l'interprétation des messages GET lol. Merci de votre aide. – BAkz

+0

Indice d'expérience personnelle: vous pouvez ignorer tout dans l'en-tête HTTP jusqu'à deux nouvelles lignes. La mise en œuvre de l'analyseur syntaxique complet pour le message RFC822/RFC2822 est une corvée - vous pouvez la reporter. – Dummy00001

+0

Ouais je sais ce que tu veux dire. Je suis confus encore = s – BAkz