使用套接字通信阻止服务器 - 客户端之间的连接

时间:2017-01-18 17:16:35

标签: c++ sockets sfml

我在使用UDP和SFML进行客户端 - 服务器连接时出现了一些奇怪的问题,我正在慢慢地想出可能出错的想法,所以也许有人能够帮助我。

目前我可以将客户端连接到服务器并从服务器向客户端发送消息。当我终止客户端应用程序并重新启动它(在同一台机器上)时,提供相同的服务器连接参数,没有任何反应。似乎没有建立连接。客户端只是在等待消息格式服务器,而服务器则在不断地同时发送消息。

我的服务器端看起来像这样:

openstack_networks

和我的客户:

std::shared_ptr<sf::UdpSocket> startUdpServer()
{
    std::cout << "Local address: ";
    std::cout << sf::IpAddress::getLocalAddress().toString() << std::endl;
    std::cout << "Public address: ";
    std::cout << sf::IpAddress::getPublicAddress().toString() << std::endl;
    std::shared_ptr<sf::UdpSocket> socket(new sf::UdpSocket());

    if(socket->bind(sf::Socket::AnyPort) != sf::Socket::Done)
        return nullptr;
    std::cout << "Server is listening to port " << socket->getLocalPort() << ", waiting for a message... " << std::endl;
    return socket;
}

std::pair<sf::IpAddress, unsigned short> runUdpServer(std::shared_ptr<sf::UdpSocket> socket)
{
    // Wait for a message
    char in[128];
    std::size_t received;
    sf::IpAddress sender;
    unsigned short senderPort;
    if (socket->receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done)
    {
        std::cout << "Connection error" << std::endl;
        return std::make_pair(sender, senderPort);
    }
    std::cout << "Message received from client " << sender << ": \"" << in << "\"" << std::endl;
    return std::make_pair(sender, senderPort);
}

void sendUdpMessage(std::shared_ptr<sf::UdpSocket> socket, std::pair<sf::IpAddress, unsigned short> config,
                    std::string message)
{
    const char* out = message.c_str();
    if (socket->send(out, sizeof(char) * message.length(), config.first, config.second) != sf::Socket::Done)
    {
        std::cout << "Message not send" << std::endl;
        return;
    }
}

void sendMessages(std::shared_ptr<sf::UdpSocket> socket, std::pair<sf::IpAddress, unsigned short> config)
{
    if(config.first != sf::IpAddress::None)
    {
        while(true)
            sendUdpMessage(socket,config,"Test msg");
    }
    else
        std::cout << "Message sending error" << std::endl;
}

auto socket = startUdpServer();
auto config = runUdpServer(socket);
std::thread messages_thread(sendMessages,socket,config);

2 个答案:

答案 0 :(得分:1)

通过网络,有两个非常重要的关键注意事项要记住UDP和TCP。

TCP - 基于连接,这意味着每当它尝试向其发送消息时,它需要在另一端有人。

UDP--基于无连接,这意味着他会将信息发送到您想要的地方。他可以发送和接收信息,但为了接收数据,他需要绑定到端口。因此,在您的服务器中,您每次都将它绑定到同一个端口。

在您的客户端,您正在给他一个端口来发送信息,而不是将他绑定到特定端口。每当您关闭客户端时,他都应该释放端口,每当您重新启动客户端时,如果您希望他能够从您的服务器接收数据,他应该绑定到同一个端口。如果你没有发生什么事情,那么数据会被发送到它所发送的IP和端口,但是没有与该端口相关联的应用程序,因此数据包丢失了。

答案 1 :(得分:1)

为了通过UDP在双方之间进行通信,每一方都需要一个唯一的(地址,端口)对。通常,服务器将其套接字绑定到固定/已知端口,客户端端口因客户端而异 - 因此允许多个客户端与同一服务器通信,每个客户端都在自己的端口上。

如果您的客户端(如此处)没有明确地将其套接字绑定到端口,则操作系统将动态分配&#34;随机&#34;未使用的端口,并在第一次使用端口时自动绑定它以发送数据。只要该客户端继续使用相同的套接字,端口号就是固定的。

但是,当您重新启动客户端时,它会获得一个 new 套接字,并且在第一次使用新套接字发送时,操作系统会将套接字绑定到新端口。但是,您的服务器假设客户端端口号仍然是从第一个客户端收到的号码。

由于它的工作方式,对于UDP服务器,通常的模式是每个消息都是独立的。服务器每次收到消息时都会记下客户端的地址和端口号,然后回复该地址/端口。服务器通常不会假设任何两个连续的消息来自同一个客户端,因为它无法知道任何给定的客户端何时消失。

(你可以在UDP上构建你自己更持久的#34;连接&#34;概念 - 例如NFS传统上做的 - 但这是需要大量工作的在设计协议时要小心谨慎。它在上述相同的基本模型中工作。)

您的客户端也可以始终显式绑定到您选择的端口。但是,这会限制您在任何一台计算机上运行一个客户端实例(实际上,在任何一个网络地址上)。