SFML TCP包接收

时间:2013-02-04 12:42:34

标签: c++ tcp sfml packet

我将一个数据包作为客户端发送到服务器,我希望服务器将该数据包发送到所有客户端,这里是代码:

#include <iostream>
#include <SFML/Network.hpp>
using namespace std;
int main()
{
int fromID; // receive data from 'fromID'
int Message; // fromID's message

sf::SocketTCP Listener;
if (!Listener.Listen(4567))
    return 1;
// Create a selector for handling several sockets (the listener + the socket associated to each client)
sf::SelectorTCP Selector;

Selector.Add(Listener);

while (true)
{
    unsigned int NbSockets = Selector.Wait();
    for (unsigned int i = 0; i < NbSockets; ++i)
    {
        // Get the current socket
        sf::SocketTCP Socket = Selector.GetSocketReady(i);

        if (Socket == Listener)
        {
        // If the listening socket is ready, it means that we can accept a new connection
            sf::IPAddress Address;
            sf::SocketTCP Client;
            Listener.Accept(Client, &Address);
            cout << "Client connected ! (" << Address << ")" << endl;

            // Add it to the selector
            Selector.Add(Client);
        }
        else
        {
            // Else, it is a client socket so we can read the data he sent
            sf::Packet Packet;
            if (Socket.Receive(Packet) == sf::Socket::Done)
            {

               // Extract the message and display it
                Packet >> Message;
                Packet >> fromID;
                cout << Message << " From: " << fromID << endl;

                //send the message to all clients
                for(unsigned int j = 0; j < NbSockets; ++j)
                {
                    sf::SocketTCP Socket2 = Selector.GetSocketReady(j);

                    sf::Packet SendPacket;
                    SendPacket << Message;
                    if(Socket2.Send(SendPacket) != sf::Socket::Done)
                        cout << "Error sending message to all clients" << endl;
                }
            }
            else
            {
              // Error : we'd better remove the socket from the selector
                Selector.Remove(Socket);
            }
        }
    }
}
return 0;

}

客户代码: 在Player类中我有这个功能:

void Player::ReceiveData()
{
 int mess;
 sf::Packet Packet;
 if(Client.Receive(Packet) == sf::Socket::Done)
 {
    Client.Receive(Packet);
    Packet >> mess;
    cout << mess << endl;
 }
}

main.cpp:

Player player;
player.Initialize();
player.LoadContent();
player.Connect();
..
..
//GAME LOOP
while(running==true)
{
   sf::Event Event;
   while(..) // EVENT LOOP
   {
   ...
   }
   player.Update(Window);
   player.ReceiveData();
   player.Draw(Window);
}

当我运行此客户端代码时,程序没有响应,冻结。 问题在于ReceiveDate()函数。

1 个答案:

答案 0 :(得分:0)

默认情况下,所有套接字(即使是SFML创建的套接字)都是阻塞的。这意味着当您尝试接收没有任何内容时,呼叫将被阻止,使您的应用程序看起来“冻结”。

您可以使用sf::SocketTCP::SetBlocking功能切换SFML套接字的阻止状态。


发送给所有客户端失败的问题是因为您使用GetSocketReady让客户端发送到。该函数仅为 ready 的客户端返回一个套接字(即先前对Wait的调用将套接字标记为有输入)。

您需要重构服务器以便以其他方式跟踪连接的客户端。常见的方法是每次在外部循环中重置和重新创建选择器,并且具有单独的连接客户端集合(例如std::vector)。