SFML TCP数据包接收 [英] SFML TCP packet receive

查看:240
本文介绍了SFML TCP数据包接收的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  #include< iostream> 
#include< SFML / Network.hpp>
using namespace std;
int main()
{
int fromID; //从'fromID'接收数据
int消息; // fromID的消息

sf :: SocketTCP Listener;
if(!Listener.Listen(4567))
return 1;
//创建一个选择器来处理多个套接字(侦听器+与每个客户端关联的套接字)
sf :: SelectorTCP Selector;

Selector.Add(Listener);

while(true)
{
unsigned int NbSockets = Selector.Wait();
for(unsigned int i = 0; i {
//获取当前套接字
sf :: SocketTCP Socket = Selector.GetSocketReady一世);

if(Socket == Listener)
{
//如果侦听套接字准备就绪,这意味着我们可以接受一个新的连接
sf :: IPAddress地址;
sf :: SocketTCP Client;
Listener.Accept(Client,& Address);
cout<< Client connected!(<< Address<<)< endl;

//将其添加到选择器
Selector.Add(Client);
}
else
{
// Else,它是一个客户端套接字,所以我们可以读取他发送的数据
sf :: Packet Packet;
if(Socket.Receive(Packet)== sf :: Socket :: Done)
{

//提取消息并显示它
Packet> >信息;
Packet>> fromID;
cout<<消息<< From:< fromID<< endl;

//将消息发送到所有客户端
for(unsigned int j = 0; j {
sf :: SocketTCP Socket2 = Selector.GetSocketReady(j);

sf :: Packet SendPacket;
SendPacket<<信息;
if(Socket2.Send(SendPacket)!= sf :: Socket :: Done)
cout< 向所有客户端发送消息时出错< endl;
}
}
else
{
//错误:我们最好从选择器中删除套接字
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>> ;
cout<<坏< endl;
}
}

main.cpp:

 玩家; 
player.Initialize();
player.LoadContent();
player.Connect();
..
..
//游戏LOOP
while(running == true)
{
sf :: Event Event;
while(..)//事件循环
{
...
}
player.Update(Window);
player.ReceiveData();
player.Draw(Window);
}

当我运行这个客户端代码时,程序没有响应,冻结。所有套接字,即使是由SFML创建的套接字,都是由以下方法创建的:

默认阻塞。这意味着当您尝试接收没有什么可接受时,调用会阻塞,使您的应用程序似乎冻结。



您可以切换阻止状态一个包含 sf :: SocketTCP :: Set blocking 函数。






发送到所有客户端失败的问题是因为您可以使用 GetSocketReady 来获取客户端发送到。该函数只为客户端 ready 返回一个套接字(即,之前调用 Wait 将套接字标记为有输入)。



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

I send a packet as client to server and I want to the server sends that packet forward to all client, here is the code:

#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;

}

Client code: in Player class I have this function :

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);
}

When I run this client code, the program not responding, freezes. The problem is with that ReceiveDate() function.

解决方案

All sockets, even the one created by SFML, are by default blocking. This means that when you try to receive when there is nothing to receive, the call will block, making your application seem "freezed".

You can toggle the blocking status of a SFML socket with the sf::SocketTCP::SetBlocking function.


The problem with sending to all clients failing is because you use GetSocketReady to get the clients to send to. That function only returns a socket for clients that are ready (i.e. the previous call to Wait marked the socket as having input).

You need to refactor the server to keep track of the connected clients in another way. The common way is to reset and recreate the selector every time in the outer loop, and have a separate collection of the connected clients (e.g. a std::vector).

这篇关于SFML TCP数据包接收的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆