Создание и подключение сокетов в c: ошибка привязки и подключения - PullRequest
0 голосов
/ 23 апреля 2020

Это моя домашняя работа, и я искал такие ресурсы, как geeksforgeeks , но я не мог понять, как исправить ошибку сбоя привязки и остановить зависание соединения. Вот мой код:

     /*
 * Assignment:
 * Write a program that optionally accepts an address and a port from the command line.
 * If there is no address/port on the command line, it should create a TCP socket and print the address
 * (i.e. server mode). If there is an address/port, it should connect to it (i.e. client mode).
 * Once the connections are set up, each side should enter a loop of receive, print what it received,
 * then send a message. The message should be “ping” from the client and “pong” from the server.
 */
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]) {
    char buffer[100];
    char *msg_server = "pong";
    char *msg_client = "ping";

    ///server mode
    if (argc==1) { //if no address/port was given
        struct sockaddr_in me, other;
        int sockfd, new_sockfd;  // listen on sock_fd, new connection on new_sockfd
        printf("No address was given. Creating socket\n");
        //create a TCP socket
        sockfd = socket(PF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {
            printf("Error: Socket is not created\n");
            return -1;
        }
        memset(&me, 0, sizeof(me));
        me.sin_family = AF_INET;
        me.sin_port = htons(8000);
        me.sin_addr.s_addr = INADDR_ANY;
        printf("IP address: %s\n",inet_ntoa(me.sin_addr));
        //bind -> listen -> accept
        if(bind(sockfd, (struct sockaddr *) &me, sizeof(me)) < 0) {
            perror("bind");
            exit(EXIT_FAILURE);
        }
        if (listen(sockfd, 3) < 0) {
            perror("listen");
            exit(EXIT_FAILURE);
        }
        if ((new_sockfd = accept(sockfd, (struct sockaddr *) &other, (socklen_t *) sizeof(other))) < 0) {
            perror("accept");
            exit(EXIT_FAILURE);
        }
        //loop of receive, printing received, sending a message
        while (1) {
            read( new_sockfd , buffer, 1000); //receive
            printf("%s\n",buffer ); //print
            send(new_sockfd, msg_server, strlen(msg_server), 0 ); //send
        }
    }
        ///Client mode
    else //there is an address/port
    {
        int sockfd, new_sockfd, port;  // listen on sock_fd, new connection on new_sockfd
        struct sockaddr_in other;
        port = atoi(argv[2]);
        printf("Address entered: %s\nPort entered: %s\n", argv[1], argv[2]);
        sockfd = socket(PF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {
            printf("Error: Socket not created\n");
            return -1;
        }
        memset(&other, 0, sizeof(other));
        other.sin_family = AF_INET;
        other.sin_addr.s_addr = INADDR_ANY;
        other.sin_port = htons(port);

        if(inet_pton(AF_INET, argv[1], &other.sin_addr)<=0)
        {
            printf("Invalid address.\n");
            return -1;
        }
        if (connect(sockfd, (struct sockaddr *)&other, sizeof(other)) < 0)
        {
            perror("connect");
            exit(EXIT_FAILURE);
        }
        //loop of receive, printing received, sending a message
        while (1) {
            send(new_sockfd, msg_client, strlen(msg_client), 0 ); //send
            read( new_sockfd , buffer, 1000); //receive
            printf("%s\n",buffer ); //print
        }
    }
    return 0;
}

Вывод показан ниже: enter image description here

Вывод в тексте:

luna@DESKTOP-HLM1VNH : / mnt / c / users / dolne / clionprojects / lab9 $ g cc lab9. c -o lab9

luna@DESKTOP-HLM1VNH: / mnt / c / users / dolne / clionprojects / lab9 $. / lab9

Адрес не указан. Создание сокета

IP-адрес: 0.0.0.0

bind: Адрес уже используется

luna@DESKTOP-HLM1VNH: / mnt / c / users / dolne / clionprojects / lab9 $. / lab9 127.0.0.1 8000

Введенный адрес: 127.0.0.1

Введен порт: 8000

^ C

I вышли из завес с ^ C или ^ Z. Если бы кто-нибудь мог дать мне советы, как исправить эти ошибки или даже как улучшить мой код, я был бы очень благодарен. Это мой первый раз сервер кодирования и материал posix. обновление: я включил функцию perror () для обработки ошибок, чтобы уточнить ошибки.

1 Ответ

2 голосов
/ 23 апреля 2020

И клиент, и сервер делают read до send, поэтому они оба изначально ожидают сообщения, которое никогда не поступит.

One из них имеет до go сначала и отправляет сообщение.

От:

Сообщение должно быть «ping» от клиент и «понг» с сервера.

Подразумевается, что клиент должен отправить первое сообщение. Это означает, что клиент должен выполнить: send и затем read (в отличие от обоих read, а затем send).

Но ни один из них не проверяет возвращаемое значение из read, поэтому ни один из них не завершится, если другой закроет сокет.

Кроме того, сервер после выполнения accept должен выполнить fork и выполнить l oop в дочернем элементе. В противном случае один и только один клиент может подключиться к серверу в данный момент времени.

...