(WINSOCK)C ++游戏服务器:TCPAccept

时间:2015-05-22 21:30:11

标签: c++ sockets tcp winsock ddos

我试图进行压力测试,以防攻击者尝试同时尝试与我的C ++游戏服务器进行大量TCP连接。

我制作了一个通过TCP端口连接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;

        std::string ip = tcpip(playerSocket);
        if(ipIsBanned(ip))
            closesocket(playerSocket);
    }
}

以下是tcplisten和tcpaccept的定义:

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

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

问题: 服务器在我的测试程序结束后停止接受连接。例如,如果我之后连接我的游戏(只请求一个连接而不是对于我的测试攻击程序,请求1000个连接),游戏甚至无法连接。我也没有在服务器上看到通过控制台输出的任何连接。最后一次连接来自攻击程序。它就好像它已经不能接受而且有些事情已经崩溃但是我无法弄清楚是什么,没有例外或错误。

这对我的服务器来说是一个很大的问题,因为任何人都可以轻易地崩溃服务器并迫使它必须重新启动才能再次开始接受新的连接。

我该怎么做才能打击这个?我的意思是我甚至尝试将最大连接数设置为30,000,但这并不起作用。即使它确实有效,但有人可能会尝试连接超过30,000次而无效。

修改

以上对tcplisten和tcpaccept函数的更深入定义:

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);
        //TEMP ADD
        sockid = INVALID_SOCKET;
        return false;
    }
    return true;
}


CSocket* CSocket::tcpaccept(int mode)
{
    //TEMP REMOVE: if(sockid<0)return NULL;
    if(sockid == INVALID_SOCKET) return NULL;
    SOCKET sock2;
    if((sock2 = accept(sockid, (SOCKADDR *)&SenderAddr, &SenderAddrSize)) != INVALID_SOCKET)
    {
        CSocket*sockit = new CSocket(sock2);
        if(mode >=1)sockit->setsync(1);
        return sockit;
    }

    return NULL;
}

编辑2: 这是AddSocket的定义:

int AddSocket(CSocket*b)
{
    for(int i = 0; i < sockets.count; i ++)
    {
        if(sockets[i] == NULL)
        {
            sockets.set(i, b);
            return i;
        }
    }
    sockets.Add(b);
    return sockets.count-1;
}

1 个答案:

答案 0 :(得分:0)

如果您使用的是Linux,则可以使用tcp_tw_reuse sysctl。