我编写了一个在Linux中使用epoll的服务器,我想测试它在真实环境中可以接受的连接数。所以我在Windows中编写了一个客户端,客户端创建了许多套接字来连接远程服务器。所以有一个问题,在服务器接受大约1700个连接后,客户端创建的新套接字无法连接服务器,错误代码为10060.我将客户端复制到另一个Windows并同时在2台PC上运行客户端,并且它们都得到了相同的结果。因此,服务器可以接受3400个连接。问题可能发生在Windows中,我绑定以修复它:
[HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \服务\ TCPIP \参数]
MaxUserPort = 65534(十进制)
MaxHashTableSize = 65536(十进制)
MaxFreeTcbs = 16000(十进制)
但它没有帮助。 有我的服务器代码:
bool GateServer::Init(std::string &port)
{
printf("Init to port %s\n", port.c_str());
m_nConnNum = 0;
m_socketfd = CreateAndBindSocket(port);
if (m_socketfd == -1)
{
abort();
}
int result = MakeSocketNonblocking(m_socketfd);
if (result == -1)
{
abort();
}
int z;
int sndbuf = 0; /* Send buffer size */
int rcvbuf = 0; /* Receive buffer size */
socklen_t optlen; /* Option length */
/*
* Get socket option SO_SNDBUF:
*/
optlen = sizeof sndbuf;
z = getsockopt(m_socketfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen);
/*
* Get socket option SON_RCVBUF:
*/
optlen = sizeof rcvbuf;
z = getsockopt(m_socketfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &optlen);
/*
* Report the buffer sizes:
*/
printf("Send buf: %d bytes\n", sndbuf);
printf("Recv buf: %d bytes\n", rcvbuf);
m_epollfd = epoll_create1(0);
if (m_epollfd == -1)
{
perror("epoll_create");
abort();
}
result = listen(m_socketfd, SOMAXCONN);
if (result == -1)
{
perror("listen");
abort();
}
return true;
}
void GateServer::Run()
{
int result = 0;
struct epoll_event events[MAXEVENTS];
result = AddEpollEvent(m_epollfd, m_socketfd, EPOLLIN | EPOLLET);//读入,边缘触发方式
if (result == -1)
{
perror("epoll_ctl");
abort();
}
/* The event loop */
while (1)
{
int n, i;
n = epoll_wait(m_epollfd, events, MAXEVENTS, -1);
HandleEvents(m_epollfd, events, n, m_socketfd);
}
close(m_socketfd);
}
void GateServer::HandleEvents(int epollfd, struct epoll_event *events, int num, int listenfd)
{
int i;
int fd;
for (i = 0; i < num; i++)
{
fd = events[i].data.fd;
if ((events[i].events & EPOLLERR) ||
(events[i].events & EPOLLHUP))
{
/* An error has occured on this fd, or the socket is not
ready for reading (why were we notified then?) */
fprintf(stderr, "epoll error\n");
printf("events = %d\n", events[i].events);
close(fd);
m_nConnNum--;
std::cout << "client " << fd << " disconnect. client num = " << m_nConnNum << std::endl;
continue;
}
else if (fd == listenfd && (events[i].events & EPOLLIN))
{
/* We have a notification on the listening socket, which
means one or more incoming connections. */
HandleAccept(epollfd, listenfd);
}
else if(events[i].events & EPOLLIN)
{
/* We have data on the fd waiting to be read. Read and
display it. We must read whatever data is available
completely, as we are running in edge-triggered mode
and won't get a notification again for the same
data. */
HandleRead(epollfd, fd);
}
else if (events[i].events & EPOLLOUT)
{
}
}
}
void GateServer::HandleAccept(int epollfd, int listenfd)
{
std::cout << "At HandleAccept." << std::endl;
int result;
while (1)
{
struct sockaddr cliaddr;
socklen_t cliaddrlen;
int clifd;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
cliaddrlen = sizeof cliaddr;
clifd = accept(listenfd, &cliaddr, &cliaddrlen);
if (clifd == -1)
{
if ((errno == EAGAIN) ||
(errno == EWOULDBLOCK))
{
break;
}
else
{
perror("accept");
break;
}
}
m_nConnNum++;
cout << "connected num = " << m_nConnNum << endl;
result = getnameinfo(&cliaddr, cliaddrlen,
hbuf, sizeof hbuf,
sbuf, sizeof sbuf,
NI_NUMERICHOST | NI_NUMERICSERV);
if (result == 0)
{
// printf("Accepted connection on descriptor %d "
// "(host=%s, port=%s)\n", clifd, hbuf, sbuf);
}
/* Make the incoming socket non-blocking and add it to the
list of fds to monitor. */
result = MakeSocketNonblocking(clifd);
if (result == -1)
{
abort();
}
result = AddEpollEvent(epollfd, clifd, EPOLLIN | EPOLLET);
if (result == -1)
{
perror("epoll_ctl");
abort();
}
}
}
void GateServer::HandleRead(int epollfd, int fd)
{
//std::cout << "At HandleRead." << std::endl;
//int done = 0;
while (1)
{
ssize_t count;
char buf[512];
count = read(fd, buf, sizeof(buf));
if (count == -1)
{
/* If errno == EAGAIN, that means we have read all
data. So go back to the main loop. */
if (errno != EAGAIN)
{
perror("read");
//done = 1;
}
break;
}
else if (count == 0)
{
/* End of file. The remote has closed the
connection. */
//done = 1;
if (m_nConnNum <= 0)
{
perror("close");
abort();
}
cout << "client = " << fd << " disconnect." << endl;
close(fd);
m_nConnNum--;
break;
}
//std::cout << "server rec : " << buf << std::endl;
/* Write the buffer to standard output */
int result = write(fd, buf, count);
if (result == -1)
{
perror("write");
abort();
}
}
}
答案 0 :(得分:0)
您的调查结果并未表明您已达到任何类型的服务器限制。它们公开了每个1700个连接的客户端限制。与更多客户端主机一起继续测试。