【发布时间】:2018-10-30 08:06:57
【问题描述】:
我一直在使用套接字 API 来了解它的工作原理。
我写了两个小程序:
- 服务器在 8080 上侦听流连接。它会向任何连接到它的人发送一条简单的消息。
- 客户端连接到 127.0.0.1:8080,并将接收到的内容转储到标准输出。它按顺序重复此 20000 次。
消息以惊人的速度流动,最高可达 ~16370 次,然后暂停数十秒,然后再次开始快速移动以完成 20000 个连接。
这个实验我已经重复了几次,我在 16370、16371 和 16372 抓到了它。重复实验的结果惊人地一致。
我的问题是:为什么它需要在 ~16370 次迭代后暂停?这里的瓶颈是什么?
FWIW,我使用的是 macOS Sierra。
我这样运行服务器代码:
clang -Wall -Werror -Wpedantic server.c -o server.out && ./server.out
和这样的客户端代码:
clang -Wall -Werror -Wpedantic client.c -o client.out && time ./client.out
这是两个程序:
服务器.c
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 8080
#define MAXMSG 512
int make_socket(int port) {
int sock;
struct sockaddr_in name;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr*) &name, sizeof(name)) < 0) {
perror("bind");
exit(1);
}
return sock;
}
int main(int argc, char** argv) {
const char hello[] = "Hello visitor ";
char buffer[MAXMSG];
int sk;
unsigned long count = 0;
strcpy(buffer, hello);
sk = make_socket(PORT);
listen(sk, 10);
printf("ready\n");
for (;;) {
count++;
sprintf(buffer + strlen(hello), "%lu", count);
int s = accept(sk, NULL, NULL);
if (send(s, buffer, strlen(buffer) + 1, 0) < 0) {
perror("send");
exit(1);
}
close(s);
printf("data socket (%d) message sent (%s)\n", s, buffer);
}
}
client.c
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 8080
#define MAXMSG 512
int make_socket() {
int sock;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}
return sock;
}
int main(int argc, char** argv) {
char buffer[MAXMSG];
int sk;
size_t i;
struct sockaddr_in addr;
strcpy(buffer, "Hello world!");
for (i = 0; i < 20000; i++) {
sk = make_socket();
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sk, (struct sockaddr*) &addr, sizeof(addr));
recv(sk, buffer, strlen(buffer) + 1, 0);
close(sk);
printf("socket (%d) message = %s\n", sk, buffer);
}
}
这是我得到客户端的最后一个标准输出:
socket (3) message = Hello visitor 16369
socket (3) message = Hello visitor 16370
socket (3) message = Hello visitor 16371
socket (3) message = Hello visitor 16372
【问题讨论】:
-
16.384 是 2^14,所以我认为它已经达到了极限,必须及时处理。也许您没有正确清理套接字,它必须等待连接超时才能进行更多操作。但这只是一个猜测,我对这个话题了解不够。
-
试试shutdown。
-
@KamilCuk 我尝试在调用
close(s)之前将shutdown(s, SHUT_RDWR);添加到客户端和服务器,但我仍然得到类似的行为 -
它是特定于操作系统的。
标签: c sockets networking