0

我有一个程序,它正在侦听端口 200。客户端连接到它后,从客户端接收到的所有数据都将写入 std::cout。如果从客户端获取数据时发生任何错误,我想重新启动托管。

ServerSocket sock;
while(true)
{
    try
    {
        uint8 buff[1000];
        std::cout << "hosting..." << std::endl;
        sock.Host(port);

        while(true)
        {
            size_t ret = sock.GetData(buff, 1000);
            buff[ret] = '\0';
            std::cout << buff << std::endl;
        }
    }
    catch(const SocketException& se)
    {
        std::cout << se.What() << std::endl;
    }
}

我第一次连接到这个一切都很好。如果我关闭客户端,则会发生 SocketException(因此开始新的托管)。

主机功能:

    m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

m_address.sin_family = AF_INET;
m_address.sin_port = htons(port);
m_address.sin_addr.S_un.S_addr = INADDR_ANY;

int optval = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(int));

int retval = bind(m_socket, reinterpret_cast<sockaddr*>(&m_address), sizeof(m_address));

if(retval == SOCKET_ERROR)
    throw SocketException("bind() error", __FUNCTION__, WSAGetLastError());

retval = listen(m_socket, SOMAXCONN);

if(retval == SOCKET_ERROR)
    throw SocketException("listen() error", __FUNCTION__, WSAGetLastError());

m_socket = accept(m_socket, NULL, NULL);

if(m_socket == INVALID_SOCKET)
    throw SocketException("accept() error", __FUNCTION__, WSAGetLastError());

我需要 setsockopt 行,因为我想在发生错误后立即绑定(并且最后一个托管套接字处于 TIME_WAIT 状态?)。没有 setsockopt 我有 bind() 错误。所以我使用 setsockopt,它让我在端口上托管没有问题。但是,当我再次启动客户端并尝试连接到主机时,没有发生错误,我可以再次发送数据。但是程序不接受任何传入连接(它仍然停留在 accept(m_socket, NULL, NULL); 等待传入连接的行)。我假设客户端可以以某种方式连接到旧套接字。那可能吗?

(注意:如果我添加 WSACleanup(); WSAStartup(MAKEWORD(2, 2), &m_wsaData); 行到主机函数,那么一切都按预期工作。我不知道为什么。WSACleanup();WSAStartup(MAKEWORD(2 , 2), &m_wsaData); 仅在我为调查此问题而制作的示例程序中帮助我。在原始程序中,2 行不起作用。)

4

1 回答 1

1

你打电话bind()listen()每个连接。您应该在服务器启动时执行一次,然后bind()重复调用。listen()accept()

同样要正确执行此操作,您应该为每个accept()调用生成一个新线程,否则人们将能够通过打开与服务器的连接然后不发送任何内容来对您的服务器进行 DOS。

于 2012-09-28T20:10:03.393 回答