Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Receiving data  (Read 6218 times)

0 Members and 1 Guest are viewing this topic.

Kerachi

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Receiving data
« on: December 18, 2017, 06:07:04 pm »
I'm trying to learn sfml network, but there are so few example, and even if I find some, those are wrong or just weird.
For example, this code:
https://github.com/SFML/SFML/wiki/Source:-Network-Chat-Example
seems okay, but in the DoStuff thread, the
Code: [Select]
sf::Packet packetSend;
globalMutex.lock();
packetSend << msgSend;
globalMutex.unlock();

socket.send(packetSend);
part constantly sending(spamming) data and it's eats a ton of processing power, however if I delete that part, then the socket.receive(packetReceive); simply won't run, even if I send data, from another client.

Why is that?
Can someone give me a good source code for client-server game program? (I don't mind if it complex)
I think I already know the basics theory, but that would be great, if someone share with me a good free article, book or video about sfml network.

I hope it's something obvious thing (just not for me :) )

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Receiving data
« Reply #1 on: December 18, 2017, 10:52:12 pm »
The "socket" example of the SDK is a good starting point. Did you have a look at it? Or maybe you're looking for more complex stuff, but in this case you should describe your request more precisely.
Laurent Gomila - SFML developer

Kerachi

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Receiving data
« Reply #2 on: December 19, 2017, 09:13:29 am »
"The "socket" example of the SDK is a good starting point."
I'm not sure what is the SDK, in this situation (Socket Mobile Developing?).

"Did you have a look at it?"
Not yet.

Yes, I'm looking for more complex stuff, since I'm developing an RPG game, and I'm trying to make it client-server, but I don't know why I can't receive data, without sending some data.
Or should I send useless data, just to keep the connection open? I mean if a client sending data to my server, then my server won't deal with it until it doesn't send anything.

Example:
Code: [Select]
//Let say I'm sending data in every second
sf::Packet packetSend;
globalMutex.lock();
packetSend << msgSend;
globalMutex.unlock();

socket.send(packetSend);

//Then this part will run in every second, but I want it to run when data arraives to the server
//However I don't want it to run constantly, cuz that would eat a lot of processing power (about 20-25%)
std::string msg;
sf::Packet packetReceive;

socket.receive(packetReceive);
if ((packetReceive >> msg) && oldMsg != msg && !msg.empty())
{
std::cout << msg << std::endl;
oldMsg = msg;
}
Because this code right now runs while(!quit), which means it runs some million times per second. (of course it depends on hardware, but it not the thing what I would like to discuss here)

I would appreciate a fast server example, even if it complicated, that would save a lot of time. (At least I hope so)

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Receiving data
« Reply #3 on: December 19, 2017, 09:43:50 am »
Laurent meant the official SFML examples: https://github.com/SFML/SFML/tree/master/examples

Alternatively, instead of copy&pasting code and randomly changing bits, it might be useful to first get a more solid understanding of network programming or how networks work in general.

Then there are the SFML tutorials: https://www.sfml-dev.org/tutorials/2.4/#network-module
And there's quite a bit information in the FAQ: https://www.sfml-dev.org/faq.php#networking

Keep in mind that SFML isn't here to teach you everything from programming, to networking, it's in your responsibility to learn the basics and only then you can use SFML to implement the gained understanding. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Kerachi

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Receiving data
« Reply #4 on: December 19, 2017, 10:39:56 am »
eXpl0it3r, I read some of https://github.com/SFML/SFML/tree/master/examples
And, yes I did read those tutorials, and I agree... but ehh then lets see my very basic server example:

All it can do:
  • acceptin connections
  • receiving message & print it (Won't work, if you don't send data)
  • delete disconnected sockets

Code: [Select]
#include <iostream>
#include <SFML/Network.hpp>

std::string msgSend;
//Since all the client constantly spamming data to the server I made this:
static std::vector<std::string> oldMessages;
//to keep track of the last sended messages, and don't handle them... (poor solution)
//Basicly it contains the client last message...
sf::Mutex globalMutex;

std::vector<sf::TcpSocket *> clients;
sf::TcpListener listener;
sf::SocketSelector selector;

bool quit = false;

void Receive_Packets(void)
{
while(!quit)
{
    if (selector.wait())
        {
            if (selector.isReady(listener))
            {
//If New client connected:
//- Create a new socket and add to the sockets list
//- Add new socket to the socket selector
//- Add oldMessages list a empty message, since the program won't allow the send the same message more times in row
//- Print new Client IP

                sf::TcpSocket *client = new sf::TcpSocket;
                //Add New Client
                if (listener.accept(*client) == sf::Socket::Done)
                {
                    clients.push_back(client);
                    selector.add(*client);
                    oldMessages.push_back("");
                    std::cout<<std::endl<<"New Client: " <<client->getRemoteAddress()<<std::endl << "Me: ";
                }

                //If listener can not accept the socket:
//- Print Clinet disconnected: Clinet IP
//- Delete newly created socket
//- Print new clients list size

                else
                {
                    std::cout<<std::endl<<"Client disconnected: "<< client->getRemoteAddress()<<std::endl;
                    client->disconnect();
                    delete(client);
                    std::cout<<"Clients: "<<clients.size()<<std::endl << "Me: ";
                }
            }

            short messageIndex=0;
            messageIndex=0; //To make sure...

            for(sf::TcpSocket *client : clients)
            {
                if (selector.isReady(*client))
                {
                    //IF I WON'T SEND SOMETHING, THEN THE RECEIVE PART WON'T RUN
                    //However if you delete the commend part, and run this code too, then it's will work
                    //but it will send data constantly, and eats about 20-25% processor power
/*
                    //Send Message
                    sf::Packet packetSend;
                    globalMutex.lock();
                    packetSend << msgSend;
                    globalMutex.unlock();
                    client->send(packetSend);
                    */

                    sf::Packet packetReceive;
                    std::string msg;

//This iterator keeps track which client what sended last time
                    std::vector<std::string>::iterator it = oldMessages.begin() + messageIndex;

                    //Receive Message
                    if(client->receive(packetReceive) == sf::Socket::Done){
                        if(packetReceive >> msg)
                        {
                            if(*it != msg && !msg.empty())
                            {
                                std::cout <<std::endl<< client->getRemoteAddress()<<": "<< msg << std::endl << "Me: ";
                                *it = msg;
                            }
                        }
                    }
                    //IF the client disconnected:
//- Print Client disconnected: Clinet IP
//- Remove Client from the selector
//- Disconnecting the client
//- Delete client socket from the clients list (vector)
//- Delete the client last message from the oldMessages list (vector)
//- Print new clients list size

                    else if(client->receive(packetReceive) == sf::Socket::Disconnected){
                        std::cout<<std::endl<<"Client disconnected: "<< client->getRemoteAddress()<<std::endl;
                        selector.remove(*client);
                        client->disconnect();
                        clients.erase(std::remove(clients.begin(), clients.end(), client), clients.end());
                        oldMessages.erase(std::remove(oldMessages.begin(), oldMessages.end(), *it), oldMessages.end());
                        std::cout<<"Clients: "<<clients.size()<<std::endl << "Me: ";
                    }
                }
                ++messageIndex;
            }
        }
    }
}

//Get a row from the user and later on the Thread
//will send it to the clients
void GetInput(void)
{
    std::cout<<"Me: ";
std::string s;
getline(std::cin,s);
if(s == "exit")
quit = true;
globalMutex.lock();
msgSend = s;
globalMutex.unlock();
}

int main()
{
    const unsigned short PORT = 53000;

    if(listener.listen(PORT) != sf::Socket::Done){
        std::cout<<"Can not use "<<PORT<<" port"<<std::endl;
        return 0;
    }
    selector.add(listener);

    sf::Thread *thread = 0;
    thread = new sf::Thread(&Receive_Packets);
    thread->launch();

//MAIN LOOP:
//- Runs while the user doesn't type "exit"

    std::cout<<"Server is ready."<<std::endl;
    while(!quit){
        GetInput();
    }

    std::cout<<"Server shut down..."<<std::endl;

//Close thread

    if(thread)
{
thread->terminate();
delete thread;
}

//Delete all the sockets from the heap

    for(int i=0;i<clients.size();++i)
        delete clients[i];
}

Try to copy and paste it somewhere, it doesn't looks so great :(

btw I didn't want to post it here, since it took some time to read, meanwhile https://github.com/SFML/SFML/wiki/Source:-Network-Chat-Example has simmilar "issue" and shorter.

Edited: I added some comments to the code
« Last Edit: December 21, 2017, 10:26:53 pm by Kerachi »

Gleade

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
Re: Receiving data
« Reply #5 on: December 20, 2017, 11:55:53 pm »
What do you mean by it "won't work" unless you send data? You can't send data over TCP without a connection, so that must be working fine for you.

Kerachi

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Receiving data
« Reply #6 on: December 21, 2017, 09:23:39 am »
I'm connecting to the server with a client successfully, and the server is printing out:
New Client: 127.0.0.1

If I'm closing a client the server prints out successfully:
Clinet Disconnected: 127.0.0.1

But whenever I send data to the server, the server should print out something like this:
"127.0.0.1: hello
Me:"
But it doesn't, only if I send data to the client before the client does.
Example:

Server send: "Hello Client"
Client send: "Hello Server"
Server print out: "127.0.0.1: Hello Server
Me:"
Client print out: "127.0.0.1: Hello Client
Me:"

However, if I do this:
Client send: "Hello Server"
Server DOES NOT print out: "127.0.0.1: Hello Server
Me:"

So as I experienced, after I send data to the client with the server, then the server will print out the last message, which arrived.

By the way, I'm using Windows 10 with Visual Studio 2017 Community.

I'm still trying to figure out what it the problem, without any success yet :(

Gleade

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
Re: Receiving data
« Reply #7 on: December 21, 2017, 11:44:50 pm »
I think I understand what you're saying now.

The connection between the client and server works. The issue is:
The client cannot send data to the server without the server first sending data?

Kerachi

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Receiving data
« Reply #8 on: December 22, 2017, 08:57:58 am »
The Client can send data to the server, the client works fine, but the server can not perceive it.

this part:
Code: [Select]
if(client->receive(packetReceive) == sf::Socket::Done){
                        if(packetReceive >> msg)
                        {
                            if(*it != msg && !msg.empty())
                            {
                                std::cout <<std::endl<< client->getRemoteAddress()<<": "<< msg << std::endl << "Me: ";
                                *it = msg;
                            }
                        }
                    }
Won't run, if I do not send data with the server to the client.
Basicly the if is false, even if it must be true.

Kerachi

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: Receiving data
« Reply #9 on: December 22, 2017, 06:16:02 pm »
Future Kerachi: There is a getline(std::cin,s); which will block your program, although I can not see any other big mistake, keep up the good work! :)