我使用套接字来同步多个远程进程。
这个想法是一个进程创建一个管理服务器端的pthread,就像这样:
void *listener(void * in) {
int sockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n = *((int *) in);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
int option = 1;
setsockopt(sockfd, SOL_SOCKET, (SO_REUSEPORT | SO_REUSEADDR), (char*) &option, sizeof (option));
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error("ERROR on binding");
if (listen(sockfd, n) < 0)
error("ERROR when listening");
clilen = sizeof (cli_addr);
int cnt = 0;
while (cnt < n) {
int newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
error("ERROR on accept");
}
cnt++;
}
close(sockfd);
return 0;
}
同时,其他进程将执行:
int sockfd;
struct sockaddr_in serv_addr;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(_managementHost); //managementHost);
if (server == NULL)
error("ERROR, no such host\n");
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(PORT);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
error("ERROR connection");
close(sockfd);
现在,我遇到的问题是,当我有很多进程尝试同时连接到服务器时,其中一些进程会抛出连接被拒绝错误。
我猜这是因为接受可能还没有准备好......事实上,我已经读到它可能会发生,但我还没有找到我的具体情况。
有人能解释一下这个问题吗?
我想到的一个可能的解决方案是为每个接受创建一个线程,但我宁愿避免它。
谢谢。
编辑:更正了服务器中套接字的双重初始化。感谢@Remy Lebeau。
最佳答案
Now, the problem I have is when I have a lot of processes trying to connect at the same time to the server, some of them are throwing connection refused errors.
监听 TCP 套接字积压了待处理的连接。 listen()
的第二个参数指定在接受之前积压队列中允许有多少个连接。如果新客户端在积压已满时尝试连接,则该客户端将被拒绝。客户端或服务器对此无能为力。客户端有责任检测错误并稍后重新连接。
您的 listener()
正在接受客户端,直到达到指定的连接数,但您也使用相同的数字作为监听积压队列大小。事件连接数和待处理连接数是两个不同的东西。如果您预计有很多客户端同时连接,则需要较大的积压大小以避免拒绝错误。但积压的大小应与您预期的流量成正比。如果您有 1000 个客户端,但它们一次仅连接 20 个,您可以将待办事项设置为 25,而不是 1000。
您的listener()
还有一些其他逻辑错误。它调用了 socket()
两次,并将两个套接字保存到同一个 sockfd
变量中,因此它泄漏了第一个套接字。您需要删除对 socket()
的第二次调用(setsockopt()
之前的调用)。您还泄漏了 accept()
返回的套接字。在使用已接受的套接字后,您需要close()
它。
关于c - 由于连接突发,套接字连接被拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39626253/