我是套接字编程的新手,我在调试以下代码时遇到了问题:
客户:
#define SIZE sizeof(struct sockaddr_in)
int main(int argc, char* argv[]) {
printf("Starting setup\n");
int sockfd;
int adder;
int sum;
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(7013);
inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr);
printf("Setup complete\n");
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket call failed.\n");
return EXIT_FAILURE;
}
else{
printf("socket: %i", sockfd);
}
//connect the socket
if (connect(sockfd, (struct sockaddr*) &server, SIZE) == -1) {
perror("Connect call failed");
return EXIT_FAILURE;
}
//Send and receive
while (!feof(stdin)) {
printf("Input an integer \n");
adder = atoi(fgets(intChar, 11, stdin));
if ((send(sockfd, &adder, 11, 0)) == -1) {
perror("Send error");
}
if (recv(sockfd, &sum, 1, 0) > 0) {
printf("%d", sum);
}
else {
printf("Server has died \n");
close(sockfd);
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
服务器:
int sum = 0;
int numconnections = 0;
int main(int argc, char* argv[]) {
int sockfd;
int newsockfd;
int adder = 0;
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(7013);
server.sin_addr.s_addr = INADDR_ANY;
printf("Starting up. \n");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
//Free port
int on = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (sockfd == -1) {
perror("Socket call failed. \n");
return EXIT_FAILURE;
}
//bind address
if (bind(sockfd, (struct sockaddr*) &server, sizeof(server)) == -1) {
perror("Bind call failed. \n");
return EXIT_FAILURE;
}
//listen
if (listen(sockfd, 5) == -1) {
perror("Listen call failed. \n");
return EXIT_FAILURE;
}
while (numconnections < 2) {
//accept a connection
printf("ready to accept connections\n");
if ((newsockfd = accept(sockfd, NULL, NULL)) == -1) {
perror("Accept call failed. \n");
continue;
}
printf("New connection detected");
numconnections++;
//spawn child to deal with it
if (fork() == 0) {
while (recv(newsockfd, &adder, 1, 0) > 0) {
printf("Sum is %d \n", sum);
printf("Adder is %d \n", adder);
sum += adder;
printf("Sending sum %d \n", sum);
send(newsockfd, &sum, 1, 0);
}
close(newsockfd);
return EXIT_SUCCESS;
}
}
close(newsockfd);
close(sockfd);
return EXIT_SUCCESS;
}
无论我是在同一台机器上还是在不同的机器上运行这些程序,当服务器收到一个套接字时,它会连续添加大约 10 次数字,就好像套接字在循环一样。
这是我从客户端提交 3 后的一些示例输出:
Starting up.
ready to accept connections
New connection detectedready to accept connections
New connection detectedSum is 0
Adder is 3
Sending sum 3
Sum is 3
Adder is 0
Sending sum 3
Sum is 3
Adder is 0
Sending sum 3
Sum is 3
Adder is 0
Sending sum 3
Sum is 3
Adder is 77
Sending sum 80
Sum is 80
Adder is 11
Sending sum 91
Sum is 91
Adder is 64
Sending sum 155
Sum is 155
Adder is 0
Sending sum 155
Sum is 155
Adder is 3
Sending sum 158
Sum is 158
Adder is 0
Sending sum 158
Sum is 158
Adder is 0
Sending sum 158
在客户端,我最初取回 3,但随后我得到一些无意义的数字,例如 4197123。
我有一种强烈的感觉,我错过了一些明显的东西。提前致谢。
最佳答案
while (recv(newsockfd, &adder, 1, 0) > 0) { ...
使用 recv() 的返回值,它是实际收到的字节数。第三个说法也是错误的。它至少应该是 sizeof(int)。或者你可以缓冲调用之间的部分接收,这是必要的,因为 TCP 没有消息边界:流可以在任何时候被分解。 (请参阅我的缓冲草图 here )
您还应该更改 send() 的第三个参数; send()
类似。
adder = atoi(fgets(intChar, 11, stdin));
if ((send(sockfd, &adder, 11, 0)) == -1) { ...
(客户端)您发送的是 int 而不是字符串也是非常错误的。
最后:不要使用feof()
,至少不要以这种方式使用。 feof() 将在 fgets() 失败后 返回非零值,NULL 参数可能会导致 atoi() 崩溃。
关于c - 套接字通信的奇怪循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20386336/