Я пишу Сервер, который использует epoll в Linux, и я хочу проверить, сколько подключений оно может принять в реальной среде. Поэтому я пишу клиент в Windows, клиент создает много сокетов для подключения удаленного сервера. Поэтому возникает вопрос: после того, как сервер принимает около 1700 подключений, новый сокет, созданный клиентом, не может подключиться к серверу, а код ошибки - 10060. Я копирую клиент в другую Windows и запускаю клиент на 2 ПК одновременно, и оба они получают одинаковый результат. Таким образом, сервер может принимать 3400 подключений. Проблемы могут иметь место в окнах, и я привязал, чтобы исправить это:C++ socket multi client connect
[HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Services \ Tcpip \ Parameters]
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();
}
}
}
Не звучит как проблема с кодированием, или это так? – Soren
Какой тип, на котором он похож? – nighcate
Неясно, какой из параметров реестра может повлиять на вашу проблему. Было бы более интересно увидеть ваш код и, в частности, код сервера. – EJP