Как поставить сервер и клиент на бесконечное соединение, пока я не остановлюсь явно - PullRequest
0 голосов
/ 11 ноября 2019

Я сделал tcp сервер и клиент. Он работает нормально, моя единственная проблема в том, что я хочу, чтобы клиент продолжал спрашивать меня о вводе, я попытался поместить его в цикл, но он работает только для одной итерации, а затем останавливается.

Server.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>     // struct sockaddr_in

    // FIX HERE
    // Let's limit our message length to a single byte.
    // This makes sending the "length" marker easier
    // without worrying about byte-ordering (endianness).
    #define MAX_LEN     255

    int main(int argc, char **argv)
    {
        int sock, newsock;
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;
        socklen_t client_addrlen; // client address length (in and out)
        int err_code;
        int num_bytes;
        char buf[MAX_LEN];
        char t[12]={0x0};
        float total=0;
        float temp=0;

        if (argc < 2) {
            fprintf(stderr, "Error, no port provided.\n");
            exit(0);
        }

        // create socket
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror("socket");
            exit(1);
        }

        // build local internet addr/port
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = INADDR_ANY;
        server_addr.sin_port = htons(atoi(argv[1]));

        // bind the socket to local internet addr/port
        err_code = bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (err_code < 0) {
            perror("bind");
            exit(2);
        }

        // put server socket in listening state
        err_code = listen(sock, 5);
        if (err_code < 0) {
            perror("listen");
            exit(3);
        }


        while (1) {
            // accept new connection (returns new socket)
            client_addrlen = sizeof(client_addr);   // must set (used as input)
            newsock = accept(sock, (struct sockaddr *)&client_addr, &client_addrlen);
            // above call also sets the client_addr and client_addrlen
            // so that we know which client is connected to the server
            if (newsock < 0) {
                perror("accept");
                exit(4);
            }

            //
            // receive data from new socket (FIX HERE)
            //
            //      Check how client sends the message with a marker.
            //      You got to receive the message according to how
            //      the client sends it.
            //
            unsigned char msglen;
            recv(newsock, &msglen, 1, 0);   // receive the length marker
            unsigned total_bytes_received = 0;
            while (total_bytes_received < msglen) {
                num_bytes = recv(newsock, buf+total_bytes_received,
                                 msglen-total_bytes_received, 0);
                if (num_bytes < 0) {
                    perror("recv");
                    exit(5);
                }
                total_bytes_received += num_bytes;
            }
    temp=atof(buf);
    total+=temp;
    sprintf(t, "%f",total);

            // display the received message
            printf("Received a datagram (%i): ", msglen); fflush(stdout);
            //write(1, "Received a datagram: ", 21);
            write(1,&t, sizeof(t));    // FIX HERE(total_bytes_received)
            printf("\n");

            //
            // acknowledge the receipt of the message from client (FIX HERE)
            //
            //      DO THE SAME AS HOW CLIENT SENDS A MESSAGE WITH A LENGTH MARKER!
            //
            char *ack_msg = "Got your message\n";
            msglen = strlen(ack_msg);
            send(newsock, &msglen, 1, 0);                   // Send marker
            num_bytes = send(newsock, ack_msg, msglen, 0);  // send ack message
            if (num_bytes < 0) {
                perror("sendto");
                exit(6);
            }

            // close new socket
            //close(newsock);
        }

        // close passive socket
        //close(sock);

        return 0;
    }

Client.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>

    // FIX HERE
    // Let's limit our message length to a single byte.
    // This makes sending the "length" marker easier
    // without worrying about byte-ordering (endianness).
    #define MAX_LEN     255

    int main(int argc, char **argv)
    {
        int sock;
        struct sockaddr_in server_addr;
        struct hostent *hp;
        char buf[MAX_LEN];
        int num_bytes;
        int err_code;


        if (argc != 3) {
            fprintf(stderr, "Usage: %s server port\n", argv[0]);
            exit(0);
        }

        // create socket
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror("socket");
            exit(1);
        }

        // resolve server name for its IP address, etc.
        hp = gethostbyname(argv[1]);
        if (NULL == hp) {
            perror("gethostbyname");
            exit(2);
        }

        // build remote server addr/port
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
        server_addr.sin_port = htons(atoi(argv[2]));

        // connect to server
        err_code = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (err_code < 0) {
            perror("connect");
            exit(3);
        }
        //while loop start
    while(1){
        // ask user for a message to be sent
        printf("Please enter a message: ");
        memset(buf , 0, MAX_LEN);
        fgets(buf, MAX_LEN, stdin);

        //
        // send message (FIX HERE)
        //
        //      With stream paradigm, you CANNOT just send your
        //      message without proper marker. Otherwise, you
        //      will not be able to know how much data to expect
        //      to receive on the receiving side.
        //
        //      For this simple example, we will send a one-byte
        //      length before each message to be sent.
        //
        unsigned char msglen = strlen(buf);
        send(sock, &msglen, 1, 0);
        num_bytes = send(sock, buf, strlen(buf), 0);
        if (num_bytes < 0) {
            perror("send");
            exit(4);
        }

        //
        // receive message (FIX HERE)
        //
        //      This got to be symmetrical. Before receiving
        //      the message, we expect to receive a one-byte
        //      length field that tells us how long the message
        //      to receive is.
        //
        //      We will receive the message in a loop as it is
        //      not guaranteed we will receive the entire message
        //      in one shot.  The length field we receive allows
        //      us to determine when to terminate the loop.
        //
        recv(sock, &msglen, 1, 0);
        unsigned total_bytes_received = 0;
        while (total_bytes_received < msglen) {
            num_bytes = recv(sock, buf+total_bytes_received,
                            msglen-total_bytes_received, 0);
            // NOTE: the parameters passed to the above recv call!!!
            if (num_bytes < 0) {
                perror("recv");
                exit(5);
            }
            total_bytes_received += num_bytes;
        }


        // display received ack message
        printf("Got an ack (%d): ", msglen);  fflush(stdout);
        //write(1, "Got an ack: ", 12);
        write(1, buf, total_bytes_received);    // FIX HERE
        printf("\n");
    }//end while loop


        // close sock to release resource
        close(sock);


        return 0;
    }

Как вы можете видеть, попытался поместить цикл while, где пользователю предлагается отправить сообщениесервер, сервер предназначен для ответа клиенту о том, что сообщение принято, и распечатывает сообщение на стороне сервера. Это все работает только один раз, после чего клиент завершает работу. Я хочу сделать так, чтобы он мог зацикливаться и спрашивать бесконечное количество раз, пока я не уйду.

...