C ++ WINSOCK tcpaccept在“攻击”后停止接受连接

时间:2015-05-23 20:15:43

标签: c++ sockets winsock ddos

我有一个C ++游戏服务器,我正在使用一个在Windows中使用winsock的网络库 。 我一直在对我的服务器进行压力测试,看看它一次可以接受多少个连接。当我使用我的游戏客户端进行连接时,它工作正常,但在我进行下面描述的压力测试后,我的游戏客户端无法再连接。

压力测试是,我使用一个简单的循环程序连接到我的服务器大约1000次,它只是启动与我的游戏服务器的tcp连接并立即关闭它。他们都连接起来。然后,之后,我尝试连接我的游戏。游戏根本没有连接。

我检查了库(见下文)中的tcpaccept()函数,没有输出。出于某种原因,在我对1000个连接的“攻击”之后,accept()停止接受连接。 什么可能使我的服务器停止接受连接?

这是我的循环摘要,它监听并接受连接并关闭它们:

function cube(n) {
  return Math.pow(n, 3);
}

function compute(n) {
  n = cube(n);
  // return jQuery promise `n`: `cube(n)`
  return $.when(n);
}

compute(5)
.done(function(data) {
  console.log(data);
});

compute(2)
.done(function(data) {
  console.log(data);
});

以下是 tcplisten,tcpaccept,CSocket :: CSocket(SOCKET),CSocket :: tcplisten(...)和CSocket :: tcpaccept(...)的定义:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>

在1000次连接压力测试后,我该怎么做才能弄清楚为什么accept()不再接受连接?它与完成后关闭连接的方式有关吗?当我这样做时,我只是打电话: closesocket(sockID)

请询问所需的任何其他代码!

修改 我刚刚注意到我的“压力测试” java程序在连接 668次后出现异常。这是例外:

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;

2 个答案:

答案 0 :(得分:1)

因为您的服务器端正在关闭套接字,所以它们很可能在time_wait中待几分钟。 Windows具有控制最大套接字和各种状态的各种参数。我猜你的程序在几分钟后重新开始工作,并且可能在事件查看器中有一些警告。

另一种选择可能是在几分钟内忽略这些插座并希望它们消失。即当你根本不回应时客户端调用closesocket,这意味着你不会招致time_wait。这通常有效,但并非总是如此。如果他们不这样做,那么你在后台慢慢调用closesocket()。

如果您真的想要,也可以重置连接,请参阅TCP option SO_LINGER (zero) - when it's required了解详细信息,但重置连接并不正常,因此请务必阅读有关So_linger以及tcp拆解如何工作的广泛内容。

答案 1 :(得分:0)

事实证明这个库有它自己关闭套接字的方法:

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),它执行关闭套接字所需的必要操作。

感谢大家的帮助。