сокеты — C ++ WINSOCK tcpaccept прекращает принимать соединения после «атаки»

У меня есть игровой сервер на C ++, и я использую сетевую библиотеку который использует winsock в Windows.
Я проводил стресс-тестирование своего сервера, чтобы узнать, сколько соединений он может принимать одновременно. Это работает нормально, когда я подключаюсь, используя свои игровые клиенты, но мои игровые клиенты больше не могут подключиться после того, как я выполню стресс-тест, описанный ниже.

Стресс-тест состоит в том, что я подключался к своему серверу около 1000 раз с помощью простой программы for loop, которая просто запускает tcp-соединение с моим игровым сервером и сразу закрывает его. Все они соединяются. Затем, после, я пытаюсь подключиться к своей игре. Игра не подключается вообще.

Я проверил функцию tcpaccept () из библиотеки (увидеть ниже), нет выхода. По какой-то причине accept () прекращает принимать соединения после моей «атаки» из 1000 соединений.
Что может заставить мой сервер просто перестать принимать соединения?

Вот мое резюме моего цикла, который слушает и принимает соединения и закрывает их:

bool serverIsOn = true;
double listen = tcplisten(12345, 30000, 1);
setnagle(listen, true);

...

while(serverIsOn){
double playerSocket = tcpaccept(listen, 1);
if(playerSocket > -1){
cout << "Got a new connection, socket ID: " << playerSocket << endl;

//add their sockID to list here!
addSockIDToList(playerSocket);

}

//Loop through list of socks and parse their messages here..
//If their message size == 0, we close their socket via closesocket(sockID);
loopThroughSocketIdsAndCloseOnLeave();
}

cout << "Finished!" << endl;

Вот определения для tcplisten, tcpaccept, CSocket :: CSocket (SOCKET), CSocket :: tcplisten (…) и CSocket :: tcpaccept (…):

double tcplisten(int port, int max, int mode)
{
CSocket* sock = new CSocket();
if(sock->tcplisten(port, max, mode))
return AddSocket(sock);
delete sock;
return -1;
}

double tcpaccept(int sockid, int mode)
{
CSocket*sock = (CSocket*)sockets.item(sockid);
if(sock == NULL)return -1;
CSocket*sock2 = sock->tcpaccept(mode);
if(sock2 != NULL)return AddSocket(sock2);
return -1;
}

...

CSocket::CSocket(SOCKET sock)
{
sockid = sock;
udp = false;
format = 0;
}

bool CSocket::tcplisten(int port, int max, int mode)
{
if((sockid = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) return false;
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if(mode)setsync(1);
if(bind(sockid, (LPSOCKADDR)&addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
closesocket(sockid);
return false;
}
if(listen(sockid, max) == SOCKET_ERROR)
{
closesocket(sockid);
sockid = INVALID_SOCKET;
return false;
}
return true;
}CSocket* CSocket::tcpaccept(int mode)
{
if(sockid == INVALID_SOCKET) return NULL;
SOCKET sock2;
if((sock2 = accept(sockid, (SOCKADDR *)&SenderAddr, &SenderAddrSize)) != INVALID_SOCKET)
{
//This does NOT get output after that 1000-'attack' test.
std::cout << "Accepted new connection!" << std::endl;
CSocket*sockit = new CSocket(sock2);
if(mode >=1)sockit->setsync(1);
return sockit;
}

return NULL;
}

Что я могу сделать, чтобы выяснить, почему accept () больше не принимает соединения после моего стресс-теста на 1000 соединений? Это как-то связано с тем, как я закрываю соединения после их завершения? Когда я делаю это, все, что я делаю, это просто звоню: closesocket (sockID).

Пожалуйста, попросите любой другой код, необходимый!

РЕДАКТИРОВАТЬ:
Я просто заметил, что мой «стресс-тест» Java-программа получает исключение после его подключения вокруг 668 раз. Вот исключение:

Exception in thread "main" java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at sockettest.SocketTest.main(SocketTest.java:63)
Java Result: 1

2

Решение

Поскольку ваша сторона сервера закрывает сокеты, они, скорее всего, сидят в time_wait в течение нескольких минут. У Windows есть различные параметры, управляющие максимальными сокетами и различными состояниями. Я предполагаю, что ваша программа снова начнет работать через несколько минут, и, возможно, в средстве просмотра событий появятся некоторые предупреждения.

Альтернативой может быть просто игнорировать эти сокеты в течение нескольких минут и надеяться, что они исчезнут. т.е. клиент вызывает closesocket, когда вы вообще не отвечаете, что означает, что вы не берете time_wait. Это часто работает, но не всегда. Если они этого не делают, то вы медленно вызываете closesocket () для них в фоновом режиме.

Если вы действительно хотите, хотя, вы можете сбросить соединение, см. Опция TCP SO_LINGER (ноль) — когда это требуется для деталей, но перезапуск соединений не является нормальным, так что определенно читайте широко о So_linger и о том, как работает tcp teardown.

1

Другие решения

Оказывается, у этой библиотеки есть собственный метод закрытия сокета:

int closesock(int sockid)
{
CSocket*sock = (CSocket*)sockets.item(sockid);
if(sock == NULL)return -1;
delete sock;
sockets.set((int)sockid, NULL);
return 1;
}

Таким образом, он получает текущий сокет через sockID в списке сокетов.
Затем, если sockID был связан с действительным сокетом, удалите объект sock и установите для него значение NULL в списке сокетов.

Проблема была в том, что я звонил только closesocket (sockID) вместо closesock (sockID) который выполнил необходимые операции, необходимые для закрытия сокета.

Спасибо всем за вашу помощь.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector