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
的最后一个元素后面 找到一个地址。
我有以下 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
的最后一个元素后面 找到一个地址。