Не удается подключиться к локальному хосту при создании собственного веб-сервера - PullRequest
0 голосов
/ 27 января 2020

Я создал веб-сервер, и пока хочу его протестировать. Я набрал https://localhost: 8080 / test. html в браузере (Chrome, также я использую MacBook Pro). Браузер отображает ERR_CONNECTION_REFUSED.

Если кто-то может помочь мне объяснить и разрешить такую ​​ситуацию, это будет очень полезно. Я пытался запустить эту программу на linux и в среде MacOS, ни одна из них не работает. Я уже искал много подобных решений онлайн, однако, ни одно из них не могло решить мою проблему. Спасибо, ребята.

Мой код здесь:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // just added
#include <netdb.h>//Network address and service translation
#include <arpa/inet.h> //For message type convertion
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/signal.h>
#include <signal.h>
#include <errno.h>

#define BUFFSIZE 2048

// port number
int port_num = 8080;

void handle(int fd) {
    printf("handle function.\n");
    char buff[BUFFSIZE + 1];
    int bytes_read = read(fd, buff, BUFFSIZE);
    printf("bytes_read: %d\n", bytes_read);
    if (bytes_read <= 0) {
        fprintf(stderr, "connection failed, or read failed.\n");
    }
    printf("Msg: %s\n", buff);
    exit(1);
}

int main(int argc, char* argv[]){

    // make sure get the port num
    /*
    if (argc != 2) {
        fprintf(stderr, "Error: Improper number of arguments used\n");
        exit(1);
    }else {
        port_num = atoi(argv[1]);
    }
    */
    // setup socket
    struct sockaddr_in server_address, client_address;
    socklen_t client_address_length = sizeof(client_address);

    // socket file descriptor
    int fd_server, fd_client;

    char buf[BUFFSIZE];
    int on = 1;

    fd_server = socket(AF_INET, SOCK_STREAM, 0);
    if (fd_server < 0) {
        fprintf(stderr, "Error: socket set up failed.\n");
        exit(1);
    }

    // I don't know what is this
    setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));

    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(port_num);
    server_address.sin_addr.s_addr = INADDR_ANY;

    // binding
    if (bind(fd_server, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {
        fprintf(stderr, "Error: binding failed.\n");
        exit(1);
    }


    // listen 
    if (listen(fd_server, 10) == -1) {
        fprintf(stderr, "Error: socket listen failed.\n");
        exit(1);
    }

    while (1) {
        // accept

        fd_client = accept(fd_server, (struct sockaddr *)&client_address, &client_address_length);
        if (fd_client == -1) {
            fprintf(stderr, "Error: accept failed.\n");
            continue;
        }
        printf("connected...\n");
        int pid = fork();
        if (!fork()) {
            // child process
            close(fd_server);

            memset(buf, 0, 2048);
            read(fd_client, buf, 2047);
            printf("%s\n", buf);
            close(fd_client);
            printf("closing...\n");
            exit(0);
        }
        close(fd_client);
    }
    return 0;
}

И после того, как я нажму на URL (https://localhost: 8080 / test. html), печатает enter image description here

1 Ответ

0 голосов
/ 29 января 2020

Две вещи:

  • Прежде всего, вы вызываете fork() дважды в своем основном l oop, поэтому вы создаете два подпроцесса для каждого соединения, в то время как вам нужно было проверить значение дано и хранится в переменной pid.
  • секунда, вы не знаете, зачем вызывать setsockopts, чтобы повторно использовать адрес, указанный сокетом ... и вы правы. Это бесполезно здесь ... Я прокомментировал это.

Я сделал первую попытку, сделав следующие изменения:

     // I don't know what is this
-    setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));
+    // setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)); // indeed, you had better not to use it.

и

         printf("connected...\n");
         int pid = fork();
-        if (!fork()) {
+        if (!pid) { // check for the value of pid, not call fork() again.
             // child process
             close(fd_server);

После этого я получаю следующий вывод:

[s000]lcu@Luiss-MacBook-Pro:~/so/59935716$ pru
connected...
connected...
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en;q=0.9
Cookie: tocTree_ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1Text-hi=tocTree:ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1:ref-jdbcconnectionpoolnew1_link; tocTree-hi=tocTree:ref-topic-group:ref-group-configuration:ref-group-connectionservice; JSESSIONID=2d890f14dcdd285f478653a16a62; treeForm_tree-hi=treeForm:tree:resources:JDBC:connectionPoolResources


closing...
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en;q=0.9
Cookie: tocTree_ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1Text-hi=tocTree:ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1:ref-jdbcconnectionpoolnew1_link; tocTree-hi=tocTree:ref-topic-group:ref-group-configuration:ref-group-connectionservice; JSESSIONID=2d890f14dcdd285f478653a16a62; treeForm_tree-hi=treeForm:tree:resources:JDBC:connectionPoolResources


closing...
connected...
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en;q=0.9
Cookie: tocTree_ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1Text-hi=tocTree:ref-topic-group:ref-group-resources:ref-group-jdbc:ref-group-jdbcconnectionpools:ref-jdbcconnectionpoolnew1:ref-jdbcconnectionpoolnew1_link; tocTree-hi=tocTree:ref-topic-group:ref-group-configuration:ref-group-connectionservice; JSESSIONID=2d890f14dcdd285f478653a16a62; treeForm_tree-hi=treeForm:tree:resources:JDBC:connectionPoolResources


closing...

(как вы видите, google chrome пытается выполнить три попытки подключения к серверу)

После некоторой ревизии, Я внес в ваш код следующие изменения, приведшие к этому:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // just added
#include <netdb.h>//Network address and service translation
#include <arpa/inet.h> //For message type convertion
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/signal.h>
#include <signal.h>
#include <errno.h>

#define BUFFSIZE 2048

// port number
int port_num = 8080;

void handle(int fd) {
    printf("handle function.\n");
    char buff[BUFFSIZE + 1];
    int bytes_read = read(fd, buff, BUFFSIZE);
    printf("bytes_read: %d\n", bytes_read);
    if (bytes_read <= 0) {
        fprintf(stderr, "connection failed, or read failed.\n");
    }
    printf("Msg: %s\n", buff);
    exit(1);
}

int main(int argc, char* argv[]){

    // make sure get the port num
    /*
    if (argc != 2) {
        fprintf(stderr, "Error: Improper number of arguments used\n");
        exit(1);
    }else {
        port_num = atoi(argv[1]);
    }
    */
    // setup socket
    struct sockaddr_in server_address, client_address;
    socklen_t client_address_length = sizeof(client_address);

    // socket file descriptor
    int fd_server, fd_client;

    char buf[BUFFSIZE];
    int on = 1;

    fd_server = socket(AF_INET, SOCK_STREAM, 0);
    if (fd_server < 0) {
        fprintf(stderr, "Error: socket set up failed.\n");
        exit(1);
    }

    // I don't know what is this
    // setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)); // indeed, you had better not to use it.

    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(port_num);
    server_address.sin_addr.s_addr = INADDR_ANY;

    // binding
    if (bind(fd_server, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {
        fprintf(stderr, "Error: binding failed.\n");
        exit(1);
    }


    // listen 
    if (listen(fd_server, 10) == -1) {
        fprintf(stderr, "Error: socket listen failed.\n");
        exit(1);
    }

    // accept
    while ((fd_client = accept(fd_server, (struct sockaddr *)&client_address, &client_address_length)) >= 0) {
        printf("connected...\n"); // do this only in the child process. Or flush stdout before forking...
        fflush(stdout); // so you get only one message (you flush the buffer before forking)
        int pid = fork();
        if (pid == 0) { // check for the value of pid, not call fork() again.
            // child process
            close(fd_server);  // good.

            memset(buf, 0, 2048);
            ssize_t n = read(fd_client, buf, sizeof buf);
            if (n > 0) {
                write(1, buf, n);  // better not consider it a null terminated string.
            }
            close(fd_client);
            printf("closing...\n");
            exit(EXIT_SUCCESS);
        }
        close(fd_client); // good.
    }

    fprintf(stderr, "Error: accept failed.\n");
    exit(EXIT_FAILURE);
}

Я не проверял функцию handle(), так как она не используется в основном коде.

You Вы получите различные версии этого кода из здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...