Программирование сокетов на C - веб-сервер - PullRequest
2 голосов
/ 08 сентября 2010

Я новичок в программировании сокетов.В настоящее время я пытаюсь разработать веб-сервер, который может обслуживать основные запросы GET и POST http из браузера.Я использую свой ноутбук как сервер и как клиент.Поэтому идея заключается в том, что я должен иметь возможность набирать http://127.0.0.1:PORT/ в Firefox, и мой веб-сервер должен иметь возможность подключиться к этому порту и начать разговор.

Пока что написанный мной код не работает.Я использую ConText и Cygwin, чтобы иметь возможность запускать и запускать программу в Windows.Я также удалил брандмауэры из порта, который я использую.Однако веб-сервер, похоже, не распознает соединение.

Есть идеи почему?Я прилагаю код, который я написал до сих пор.Любая помощь будет принята с благодарностью.На данный момент программа не проходит мимо «Прослушивание порта ...».Я выделил ошибку, и кажется, что она застряла в утверждении, которое я выделил.

/* 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);
}

1 Ответ

2 голосов
/ 08 сентября 2010

getaddrinfo() может возвращать несколько записей, в том числе IPv6.И это может быть вашей проблемой.

Обратите внимание, что после вызова getaddrinfo() проверка ошибок отсутствует.

Если вы хотите, чтобы браузер смог подключиться к "127.0.0.1:PORT", выследует либо:

  • bind() на INADDR_LOOPBACK и ПОРТ без какой-либо помощи из getaddrinfo()
  • , правильно настроить вызов на getaddrinfo(), установить ai_family на AF_INET (так что у вас есть только IPv4).

Обратите внимание, что если первый параметр getaddrinfo() равен NULL, то возвращаемый адрес будет установлен в INADDR_ANY / IN6ADDR_ANY, что означает, что ваш сервер также будет приниматьсоединения снаружи.Чтобы ограничить соединения локальным хостом, установите для первого параметра значение «localhost» вместо NULL.


Чтобы увековечить кусок, вот мой код дампера результата getaddrinfo():

    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 );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...