wiredmark
wiredmark

Reputation: 1108

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.

Upvotes: 0

Views: 1637

Answers (2)

alk
alk

Reputation: 70893

This line

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

tries to read from the listening socket. This does not make sense.

You need to read from the accepted socket. So it should be:

 while ((n = read(connfd, recvline, sizeof(recvline))) > 0) {

Moreover it should be

 while ((n = read(connfd, recvline, sizeof(recvline) - 1)) > 0) {

as after the read() you do

    recvline[n] = '\0';

For the OP's source if you'd have read sizeof recvline bytes recvline[n] would address one behind the last element of recvline.

Upvotes: 2

szpal
szpal

Reputation: 647

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);
        }
    }

Upvotes: 2

Related Questions