Home > Back-end >  C Socket TCP, send array to server and response back to client in loop
C Socket TCP, send array to server and response back to client in loop

Time:09-25

I'm very new to socket and TCP, I'm trying to send an array of Int to the server, do some sorting and calculating, then send back the result to the client and repeat.

I tried a few different ways, I either got the result after I close the client or got into a infinite loop.

What is the proper way to keep reading from the client until the client hit EOF?

Here is my server code.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char const *argv[]) {
    struct sockaddr_in server, client;
    int sock, csock, readSize, addressSize;
    char buf[256];

    bzero(&server, sizeof(server));
    server.sin_family = PF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_port = htons(5999);

    sock = socket(PF_INET, SOCK_STREAM, 0);
    bind(sock, (struct sockaddr*)&server, sizeof(server));
    listen(sock, 5);

    addressSize = sizeof(client);
    csock = accept(sock, (struct sockaddr *)&client, &addressSize);

    int values[5];

    while (read(csock, values, sizeof(values))) {

        // Some sorting and calculating here

        for (int i = 0; i < 5; i  ) {
            printf("%d ", values[i]);
        }
    }
    close(sock);
    return 0;
}

And here is my client code.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char const *argv[]) {
    struct sockaddr_in server;
    char buf[256];
    int sock;

    bzero(&server, sizeof(server));
    server.sin_family = PF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_port = htons(5999);

    sock = socket(PF_INET, SOCK_STREAM, 0);
    connect(sock, (struct sockaddr *)&server, sizeof(server));

    while (1) {
        int values[5] = {0};

        for (int i = 0; i < 5; i  ) 
            scanf("%d", &values[i]);
        
        write(sock, values, sizeof(values));
    }
    return 0;
}

Thanks for your help!

CodePudding user response:

As noted, you should check all return value for errors (I didn't check inet_addr's return value but you should). Not sure if this was condition you were concerned about but if I do Ctrl-D on the client, scanf will return EOF, and you didn't check for it. This mean 0 values were being sent to server (forever). If you start client before server you now get an error. Also removed variables not used, and wrong type for addressSize. Finally, added a little more output so it's easier to see what is going on:

server:

#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>

int main(int argc, char const *argv[]) {
    struct sockaddr_in server, client;
    int sock, csock;
    socklen_t addressSize;

    bzero(&server, sizeof(server));
    server.sin_family = PF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_port = htons(5999);

    sock = socket(PF_INET, SOCK_STREAM, 0);
    if(sock == -1) {
        printf("socket: %s\n", strerror(errno));
        return 1;
    }
    if(bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1) {
        printf("bind: %s\n", strerror(errno));
        return 1;
    }
    if(listen(sock, 5) == -1) {
        printf("listen: %s\n", strerror(errno));
        return 1;
    }

    addressSize = sizeof(client);
    csock = accept(sock, (struct sockaddr *)&client, &addressSize);
    if(csock == -1) {
        printf("listen: %s\n", strerror(errno));
        return 1;
    }

    int values[5];
    ssize_t n;
    while ((n = read(csock, values, sizeof(values)))) {
        printf("read %zd\n", n);
        if(n <= 0) break;
        for (int i = 0; i < n; i  ) {
            printf("%d ", values[i]);
        }
        printf("\n");
    }
    close(sock);
    return 0;
}

and client:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

int main(int argc, char const *argv[]) {
    struct sockaddr_in server;
    char buf[256];
    int sock;

    bzero(&server, sizeof(server));
    server.sin_family = PF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_port = htons(5999);

    sock = socket(PF_INET, SOCK_STREAM, 0);
    if(sock == -1) {
        printf("socket: %s\n", strerror(errno));
        return 1;
    }
    if(connect(sock, (struct sockaddr *)&server, sizeof(server)) == -1) {
        printf("connect: %s\n", strerror(errno));
        return 1;
    }


    while (1) {
        int values[5] = {0};

        for (int i = 0; i < 5; i  ) {
            int r = scanf("%d", &values[i]);
            if(r == EOF) {
                return 0;
            }
        }
        ssize_t n = write(sock, values, sizeof(values));
        if(n == -1) {
            printf("write: %s\n", strerror(errno));
            return 1;
        }
        printf("wrote %zd\n", n);
    }
    return 0;
}
  • Related