Client/Server 在 C 中无限循环失败
Client/Server in C infinite loop fails
我正在使用 C 在 linux 中实现一个 client/server,在启动客户端和服务器之后,服务器正在等待来自客户端的查询,这似乎正在工作,但是,我希望服务器能够不断等待查询。然而它一直不停地循环,而不是等待来自客户端的新查询。
server.c:
int main(void)
{
int sockfd, newsockfd, portno, clilen, connfd = 0;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
{
printf("setsockopt failed\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
portno = 8888;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("bind failed\n");
exit(0);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
printf("accept failed\n");
exit(0);
}
printf("[Server] Connected\n");
char query[BUFFER_SIZE];
char result[BUFFER_SIZE];
while (1)
{
connfd = read(newsockfd, query, 20);
if (connfd > 0)
{
printf("success\n");
}
connfd = write(newsockfd, "I got your message", 18);
if (connfd >= 0)
{
printf("write back worked\n");
}
//close(newsockfd);
//close(sockfd);
sleep (1);
}
printf("%d", connfd);
printf("[Server] Done\n");
return 0;
}
如您所见,我已经尝试添加关闭命令,但它们似乎所做的只是完全停止连接,这意味着我无法在第一个之后发送查询。
client.c:
int main(void)
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
portno = 8888;
server = gethostbyname("localhost");
if (server == NULL)
{
printf("gethostbyname failed\n");
exit(0);
}
memset((char *)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((void*)&serv_addr.sin_addr.s_addr, (void*)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("connect failed\n");
exit(0);
}
printf("[Client] Connected\n");
char query[BUFFER_SIZE];
char result[BUFFER_SIZE];
while (1)
{
memset(query, 0, BUFFER_SIZE);
fgets(query, BUFFER_SIZE, stdin);
if(strncmp(query, "exit", 4) == 0)
{
break;
}
n = write(sockfd, query, sizeof(query));
if (n < 0) {
printf("can't write\n");
}
bzero(result, BUFFER_SIZE);
n = read(sockfd, result, BUFFER_SIZE);
if (n < 0) {
printf("can't read back from server\n");
}
printf("%s\n", result);
sleep(1);
}
close(sockfd);
return 0;
}
使用此代码,服务器将继续运行并无限地写回客户端 "I got your message"。我如何让它等待?
尝试添加 close(newsockfd) 但是一旦我这样做,它只允许我联系服务器一次,来自客户端的第二个查询失败。
客户端的问题是这样的:
n = write(sockfd, query, sizeof(query));
sizeof(query)
等同于 BUFFER_LEN
。当服务器执行时:
connfd = read(newsockfd, query, 20);
对于客户端发送的每个查询,它将成功 BUFFER_LEN / 20
次。这不是无限循环,但如果 BUFFER_LEN
很大,它会重复很多次。
客户端不应发送整个 query
缓冲区,而应发送从 stdin
读取的行。它应该做的:
n = write(sockfd, query, strlen(query));
另请注意,无法保证在服务器中对 read()
的单次调用会读取客户端写入的所有内容,它可能会拆分为多个调用。由于您的输入是用换行符分隔的(因为您在客户端中使用 fgets()
),因此您应该继续阅读直到获得换行符。
有关详细信息,请参阅 difference between sizeof and strlen in c
我正在使用 C 在 linux 中实现一个 client/server,在启动客户端和服务器之后,服务器正在等待来自客户端的查询,这似乎正在工作,但是,我希望服务器能够不断等待查询。然而它一直不停地循环,而不是等待来自客户端的新查询。
server.c:
int main(void)
{
int sockfd, newsockfd, portno, clilen, connfd = 0;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
{
printf("setsockopt failed\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
portno = 8888;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("bind failed\n");
exit(0);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
printf("accept failed\n");
exit(0);
}
printf("[Server] Connected\n");
char query[BUFFER_SIZE];
char result[BUFFER_SIZE];
while (1)
{
connfd = read(newsockfd, query, 20);
if (connfd > 0)
{
printf("success\n");
}
connfd = write(newsockfd, "I got your message", 18);
if (connfd >= 0)
{
printf("write back worked\n");
}
//close(newsockfd);
//close(sockfd);
sleep (1);
}
printf("%d", connfd);
printf("[Server] Done\n");
return 0;
}
如您所见,我已经尝试添加关闭命令,但它们似乎所做的只是完全停止连接,这意味着我无法在第一个之后发送查询。
client.c:
int main(void)
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("socket failed\n");
exit(0);
}
portno = 8888;
server = gethostbyname("localhost");
if (server == NULL)
{
printf("gethostbyname failed\n");
exit(0);
}
memset((char *)&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((void*)&serv_addr.sin_addr.s_addr, (void*)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("connect failed\n");
exit(0);
}
printf("[Client] Connected\n");
char query[BUFFER_SIZE];
char result[BUFFER_SIZE];
while (1)
{
memset(query, 0, BUFFER_SIZE);
fgets(query, BUFFER_SIZE, stdin);
if(strncmp(query, "exit", 4) == 0)
{
break;
}
n = write(sockfd, query, sizeof(query));
if (n < 0) {
printf("can't write\n");
}
bzero(result, BUFFER_SIZE);
n = read(sockfd, result, BUFFER_SIZE);
if (n < 0) {
printf("can't read back from server\n");
}
printf("%s\n", result);
sleep(1);
}
close(sockfd);
return 0;
}
使用此代码,服务器将继续运行并无限地写回客户端 "I got your message"。我如何让它等待? 尝试添加 close(newsockfd) 但是一旦我这样做,它只允许我联系服务器一次,来自客户端的第二个查询失败。
客户端的问题是这样的:
n = write(sockfd, query, sizeof(query));
sizeof(query)
等同于 BUFFER_LEN
。当服务器执行时:
connfd = read(newsockfd, query, 20);
对于客户端发送的每个查询,它将成功 BUFFER_LEN / 20
次。这不是无限循环,但如果 BUFFER_LEN
很大,它会重复很多次。
客户端不应发送整个 query
缓冲区,而应发送从 stdin
读取的行。它应该做的:
n = write(sockfd, query, strlen(query));
另请注意,无法保证在服务器中对 read()
的单次调用会读取客户端写入的所有内容,它可能会拆分为多个调用。由于您的输入是用换行符分隔的(因为您在客户端中使用 fgets()
),因此您应该继续阅读直到获得换行符。
有关详细信息,请参阅 difference between sizeof and strlen in c