我正在使用套接字来同步多个远程进程。
这个想法是一个进程创建了一个管理服务器端的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。
答案 0 :(得分:1)
现在,我遇到的问题是当我有很多进程试图同时连接到服务器时,其中一些会抛出连接拒绝错误。
侦听TCP套接字具有待处理连接的积压。 listen()
的第二个参数指定在接受之前允许在积压队列中连接的连接数。如果新客户端在待办事项已满时尝试连接,则拒绝客户端。客户端或服务器无法做到这一点。客户有责任检测错误并在以后重新连接。
您的listener()
正在接受客户端,直到达到指定数量的连接,但您也使用相同的号码作为侦听积压队列大小。活动连接数和挂起连接数是两回事。如果您希望许多客户端同时连接,则需要大量的积压大小以避免拒绝错误。但是积压的大小应该与您期望的流量成比例。如果您有1000个客户端,但它们一次只能连接20个,那么您可以将待办事项设置为25,而不是1000.
您的listener()
还有一些其他逻辑错误。它正在调用socket()
两次并将两个套接字保存到同一个sockfd
变量,因此它泄漏了第一个套接字。您需要删除对socket()
(setsockopt()
之前的那个)的第二次调用。您还泄漏了accept()
返回的套接字。在使用它之后,你需要close()
一个被接受的套接字。
答案 1 :(得分:0)
通过调用fork为每个客户端生成一个子项,让您的服务器并发。最简单的方法,IMO。避免线程并停止连接拒绝错误。
编辑:你也可以考虑预先分叉你的服务器。你必须研究如何处理锁定接受(如果你完全锁定)。