Search code examples
clinuxsocketsread-write

C server socket's read function writing dirty buffer


I have the following C server and client:

SERVER

int main(int argc, char **argv) {
    int listenfd, connfd, n;
    struct sockaddr_in servaddr;
    char recvline[1025];  

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket Error");
        exit(1);
    }
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(1024);

    if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        perror("Bind Error");
        exit(1);
    }
    if (listen(listenfd, 1024) < 0) {
        perror("Listen Error");
        exit(1);
    }

    while(1) {
        printf("Waiting connection...\n");

        if ((connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) < 0) {
            perror("Accept Error");
            exit(1);
        }

        printf("Waiting for input.\n");   

        while ((n = read(listenfd, recvline, sizeof(recvline))) > 0) {
            recvline[n] = '\0';
            if (fputs(recvline, stdout) == EOF) {
                fprintf(stderr,"fputs Error\n");
                exit(1);
            }
        }

        printf("Read string: %s", recvline);
        close(connfd);
    }
   }

CLIENT

int main(int argc, char **argv) {
    int sockfd, connfd, n;
    struct sockaddr_in servaddr;
    char buff[1025], matricola[15];

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket Error");
        exit(1);
    }

    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(1024);

    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {
        fprintf(stderr,"inet_pton Error for %s\n", argv[1]);
        exit (1);
    }

    if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        fprintf(stderr,"Connect Error\n");
        exit(1);
    }

    printf("Matricola: ");
    fflush(stdin);    
    scanf("%s", matricola);    
    strcpy(buff, matricola);    
    if (write(sockfd, buff, strlen(buff)) != strlen(buff)) {    
        perror("Write Error");   
        exit(1);    
    }    
    close(connfd);
    }

I'm under Linux, I can start the server correctly from terminal that starts listening, but when I open another terminal instance and start the client, the server automatically executes the rest of the code and prints Read string: ### (random characters like dirty buffer). Is this because the server is not waiting for the client to write? What am I doing wrong in this code?

What I tought was that the server didn't wait for the client to write something, so I tried to add a sleep(10) before the server's read command, but nothing changes.

EDIT: I edited the read function from

n = read(listenfd, recvline, strlen(recvline) + 1)) > 0

to

n = read(listenfd, recvline, sizeof(recvline))) > 0

But still it doesn't fix the issue.


Solution

  • Change your inner while cycle to read from the connected file descriptor, not the listening file descriptor, like this:

     while ((n = read(connfd, recvline, strlen(recvline) + 1)) > 0) {
            recvline[n] = '\0';
            if (fputs(recvline, stdout) == EOF) {
                fprintf(stderr,"fputs Error\n");
                exit(1);
            }
        }