C服务器套接字的读函数写脏缓冲区

C server socket's read function writing dirty buffer

我有以下 C 服务器和客户端:

服务器

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] = '[=10=]';
            if (fputs(recvline, stdout) == EOF) {
                fprintf(stderr,"fputs Error\n");
                exit(1);
            }
        }

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

客户

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

我在Linux下,我可以从开始监听的终端正确启动服务器,但是当我打开另一个终端实例并启动客户端时,服务器会自动执行其余代码并打印读取字符串:###(脏缓冲区等随机字符)。这是因为服务器没有等待客户端写入吗?我在这段代码中做错了什么?

我想的是服务器没有等待客户端写东西,所以我尝试在服务器的读取命令之前添加一个sleep(10),但没有任何变化。

编辑:我从

编辑了读取函数
n = read(listenfd, recvline, strlen(recvline) + 1)) > 0

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

但还是没有解决问题。

更改内部 while 循环以从连接的文件描述符而不是侦听文件描述符中读取,如下所示:

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

这一行

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

尝试从侦听套接字中读取。这没有意义。

您需要从接受的套接字中读取。所以应该是:

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

而且应该是

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

就像在 read() 之后一样

    recvline[n] = '[=13=]';

对于 OP 的源代码,如果您已经阅读了 sizeof recvline 个字节,recvline[n] 将在 recvline 的最后一个元素后面 找到一个地址。