我将一个数据包作为客户端发送到服务器,我希望服务器将该数据包发送到所有客户端,这里是代码:
#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()函数。
答案 0 :(得分:0)
默认情况下,所有套接字(即使是SFML创建的套接字)都是阻塞的。这意味着当您尝试接收没有任何内容时,呼叫将被阻止,使您的应用程序看起来“冻结”。
您可以使用sf::SocketTCP::SetBlocking
功能切换SFML套接字的阻止状态。
发送给所有客户端失败的问题是因为您使用GetSocketReady
让客户端发送到。该函数仅为 ready 的客户端返回一个套接字(即先前对Wait
的调用将套接字标记为有输入)。
您需要重构服务器以便以其他方式跟踪连接的客户端。常见的方法是每次在外部循环中重置和重新创建选择器,并且具有单独的连接客户端集合(例如std::vector
)。