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

Author Topic: Server can only receive one message at a time?  (Read 8771 times)

0 Members and 1 Guest are viewing this topic.

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Server can only receive one message at a time?
« on: September 17, 2012, 09:16:17 am »
I haven't tested client -> server -> client yet, just client -> server for now.
Unfortunately, I'm only able to send one message per connection.
Client
int main()
{
        sf::SocketTCP Client;
    // Create the main rendering window
    sf::RenderWindow App(sf::VideoMode(480, 320, 32), "Window");
        const sf::Input& Input = App.GetInput();
    cout << "Type LEFT to connect, RIGHT to send a message, UP to disconnect" << endl;
    // Start game loop
    while (App.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
                        if(Input.IsKeyDown(sf::Key::Left)){
                                if (Client.Connect(4567, "127.0.0.1") != sf::Socket::Done)
                                {
                                        // Error...
                                        cout << "error" << endl;
                                }
                                else cout << "connected" << endl;
                        }
                        else if(Input.IsKeyDown(sf::Key::Right)){
                                cout << "right pressed" << endl;
                                char Buffer[] = "Hi guys !";
                                if (Client.Send(Buffer, sizeof(Buffer)) != sf::Socket::Done)
                                {
                                        // Error...
                                        cout << "error sending message" << endl;
                                }
                        }
                        else if(Input.IsKeyDown(sf::Key::Up)){
                                Client.Close();
                                cout << "disconnected" << endl;
                        }
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }

        // Clear the screen (fill it with black color)
        App.Clear(sf::Color(255, 255, 255));

        // Display window contents on screen
        App.Display();
    }

    return EXIT_SUCCESS;
}
 

Left button connects, right button sends a message: "Hi guys !", up button disconnects/closes the socket.
Now on my server...
Server
void ThreadFunction(void* UserData)
{
        Server *server = (Server*)UserData;
        char Buffer[128];
        std::size_t Received;

        while(true){
                sf::IPAddress ClientAddress;
                if (server->Listener.Accept(server->Client, &ClientAddress) != sf::Socket::Done)
                {
                        // Error...
                        //cout << "Error listening..." << endl;
                }
                else{
                        cout << "Got a connection!" << endl;
                }

                if (server->Client.Receive(Buffer, sizeof(Buffer), Received) != sf::Socket::Done)
                {
                        // Error...
                        continue;
                }
                else{
                        cout << "Message: " << Buffer << endl;
                }
        }
}
 

I can connect, and send a message, but just one message.
If I disconnect and connect again, I can send a message, but only one.

Not sure what's going on. I should be able to send multiple ones.
« Last Edit: September 17, 2012, 09:20:14 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Server can only receive one message at a time?
« Reply #1 on: September 17, 2012, 09:24:07 am »
Your server does this:
infinite loop
{
    wait for a new client
    wait a message from this client
}
So after it has received a message, it waits for a new client.

And in your client code, you shouldn't mix events and inputs. If you want to react to single key press events, you should use the information contained in your sf::Event structure inside your event loop.
Laurent Gomila - SFML developer

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Server can only receive one message at a time?
« Reply #2 on: September 17, 2012, 05:31:54 pm »
Not really sure how to fix the problem for the server.
Don't we need to continuously listen for new connections using a loop?

I'm  a bit clueless on where in my program these codes need to be.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Server can only receive one message at a time?
« Reply #3 on: September 17, 2012, 05:35:59 pm »
Quote
Don't we need to continuously listen for new connections using a loop?
Yes, but while the socket waits for new connections, the entire thread is blocked and cannot do anything else.

The solutions that you can use are:
- switch to non-blocking sockets
- use more threads to avoid actions blocking each other
- use a selector

See the tutorials and documentation for more details :)
Laurent Gomila - SFML developer

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Server can only receive one message at a time?
« Reply #4 on: September 17, 2012, 06:32:32 pm »
Well I tried non-blocking sockets:
        Listener.SetBlocking(false);
        Client.SetBlocking(false);
 

Can still send one message per connection.

I've also tried using different threads:
void ThreadNet(void* UserData){
        Server *server = (Server*)UserData;
        char Buffer[128];
        std::size_t Received;
        while(true){
                if (server->Client.Receive(Buffer, sizeof(Buffer), Received) != sf::Socket::Done)
                {
                        // Error...
                        continue;
                }
                else{
                        cout << "Message: " << Buffer << endl;
                }
        }
}

void ThreadFunction(void* UserData)
{
        Server *server = (Server*)UserData;

        while(true){
                sf::IPAddress ClientAddress;
                if (server->Listener.Accept(server->Client, &ClientAddress) != sf::Socket::Done)
                {
                        // Error...
                        //cout << "Error listening..." << endl;
                }
                else{
                        cout << "Got a connection!" << endl;
                }
        }
}
 

Still just one message per connection...
« Last Edit: September 17, 2012, 08:20:24 pm by Laurent »

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Server can only receive one message at a time?
« Reply #5 on: September 17, 2012, 08:26:41 pm »
I've also tried using a selector.
Only this time, I can't receive any messages, besides the one when they connect to my server:
void ThreadFunction(void* UserData)
{
        Server *server = (Server*)UserData;
        char Buffer[128];
        std::size_t Received;
        while(true){
                unsigned int NbSockets = server->Selector.Wait();
                for(unsigned int i = 0; i < NbSockets; ++i){
                        sf::SocketTCP Socket = server->Selector.GetSocketReady(i);
                        //Look for new connections
                        if(Socket == server->Listener){
                                sf::IPAddress Address;
                                sf::SocketTCP Client;
                                server->Listener.Accept(Client, &Address);
                                cout << "Got a client" << endl;
                                server->Selector.Add(Client);
                        }
                        //Read data from clients
                        else{
                                sf::Packet Packet;
                                if(Socket.Receive(Packet) == sf::Socket::Done){
                                        //Get the message
                                        std::string Message;
                                        //Put whatever is in the Packet to the string
                                        Packet >> Message;
                                        cout << "Message: " << Message << endl;
                                }
                                else{
                                        server->Selector.Remove(Socket);
                                }
                        }
                }
        }

}
 

What I'm using to send a message:
                                char Buffer[] = "Hi guys !";
                                if (Client.Send(Buffer, sizeof(Buffer)) != sf::Socket::Done)
                                {
                                        // Error...
                                        cout << "error sending message" << endl;
                                }
 
« Last Edit: September 17, 2012, 10:12:47 pm by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Server can only receive one message at a time?
« Reply #6 on: September 17, 2012, 10:13:37 pm »
But... what is your main thread doing while the network thread is running?
Laurent Gomila - SFML developer

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Server can only receive one message at a time?
« Reply #7 on: September 18, 2012, 05:29:45 am »
It's asking for commands.
Here's my entire main.cpp for my server:
/************************************************************
SERVER
************************************************************/

#include <iostream>
#include <string>
#include "Server.h"
#include <SFML/System.hpp>
using namespace std;

int command(Server *s, std::string line);
void ThreadFunction(void* UserData);

bool running;

void ThreadFunction(void* UserData)
{
        Server *server = (Server*)UserData;
        char Buffer[128];
        std::size_t Received;
        while(true){
                unsigned int NbSockets = server->selector.Wait();
                for(unsigned int i = 0; i < NbSockets; ++i){
                        sf::SocketTCP Socket = server->selector.GetSocketReady(i);
                        //Look for new connections
                        if(Socket == server->Listener){
                                sf::IPAddress Address;
                                sf::SocketTCP Client;
                                server->Listener.Accept(Client, &Address);
                                cout << "Got a client" << endl;
                                server->selector.Add(Client);
                        }
                        //Read data from clients
                        else{
                                sf::Packet Packet;
                                if(Socket.Receive(Packet) == sf::Socket::Done){
                                        //Get the message
                                        std::string Message;
                                        //Put whatever is in the Packet to the string
                                        Packet >> Message;
                                        cout << "Message: " << Message << endl;
                                }
                                else{
                                        server->selector.Remove(Socket);
                                }
                        }
                }
        }

}

//Entry
int main(){
        Server server;
        sf::Thread thread(&ThreadFunction, &server);
        running = true;
        thread.Launch();
        string line;
        cout << "=========================="    << endl;
        cout << "Welcome to the NetServer."             << endl;
        cout << "=========================="    << endl;
        cout << endl;
        cout << "===================================================="          << endl;
        cout << "Enter a command. For a list of commands type \"help\"."        << endl;
        cout << "===================================================="          << endl;
        while (running){
                int ret;
                if(std::getline(cin, line)){
                        if(ret = command(&server, line) != 0)
                                return ret;
                }
        }
}

//Loop
int command(Server *server, std::string line){
        cout << endl;
        //Process line
        if(line == "help"){
                cout    << "<LIST OF COMMANDS:>" << endl;
                cout    << "help        - Displays help"        << endl
                                << "start       - Starts the server"    << endl
                                << "stop        - Stops the server"     << endl;
        }
        else if(line == "start"){
                server->start();
        }
        else if(line == "stop"){
                server->stop();
        }
        else{
                cout << endl;
                cout << "=========================" << endl;
                cout << "Invalid. Enter a command." << endl;
                cout << "=========================" << endl;
                return 0;
        }
        cout << endl;
        cout << "================" << endl;
        cout << "Enter a command." << endl;
        cout << "================" << endl;
        return 0;
}
 
« Last Edit: September 18, 2012, 08:17:52 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Server can only receive one message at a time?
« Reply #8 on: September 18, 2012, 08:18:12 am »
Can you please use the code=cpp tag so that I can stop editing all your messages?
Laurent Gomila - SFML developer

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Server can only receive one message at a time?
« Reply #9 on: September 18, 2012, 08:25:38 am »
Sorry, didn't know I could do that.
Do you know what may be the problem?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Server can only receive one message at a time?
« Reply #10 on: September 18, 2012, 09:13:55 am »
Can you show the code of the Server class?
Laurent Gomila - SFML developer

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Server can only receive one message at a time?
« Reply #11 on: September 18, 2012, 11:16:15 pm »
#include "Server.h"
#include <iostream>
using namespace std;
Server::Server(){
        started = false;
        Listener.SetBlocking(false);
}

void Server::start(){
        if(!started){
                //Check TCP Socket
                cout << "Attempting to listen on TCP port: 4567...." << endl;
                if (!Listener.Listen(4567))
                {
                        // Error...
                        cout << "Could not listen on TCP port: 4567." << endl;
                        return;
                }
                cout << "Listening on port 4567" << endl;
                started = true;
                cout << "Server started." << endl;

                selector.Add(Listener);
        }
        else{
                cout << "Server is all ready running." << endl;
        }
}

void Server::stop(){
        cout << "Stopping server..." << endl;
        started = false;
        unsigned int NbSockets = selector.Wait();
        for(unsigned int i = 0; i < NbSockets; ++i){
                selector.GetSocketReady(i).Close();
        }
}
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Server can only receive one message at a time?
« Reply #12 on: September 19, 2012, 07:48:47 am »
Don't mix selectors and non-blocking sockets, it doesn't make sense. And don't forget to check the result of the Accept function.
Laurent Gomila - SFML developer

Grimlen

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: Server can only receive one message at a time?
« Reply #13 on: September 20, 2012, 06:39:48 am »
Well I've redone my entire server and client.
Unfortunately I'm still getting the same result as before.
I can only get one message at a time per client/connection....

CLIENT:
/************************************************************
CLIENT
************************************************************/

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Network.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>

using namespace std;
////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////
int main()
{
        //Server we are connecting to (via TCP)
        bool closedConnection = false; //if we closed the socket yet or not
        sf::SocketTCP Server;
        Server.SetBlocking(false); //It honestly makes no difference whether it's true/false, same problem still
        char Message1[] = "Hello!";
        char Message2[] = "Again!";
        cout << "test" << endl;
       
        if (Server.Connect(4567, "127.0.0.1") != sf::Socket::Done)
        {
                // Error...
                cout << "Unable to connect to server" << endl;
        }
        else{
                cout << "Connected to server" << endl;
        }
        if (Server.Send(Message1, sizeof(Message1)) != sf::Socket::Done)
        {
                // Error...
        }
        else{
                cout << "Sent message to server" << endl;
        }
        if (Server.Send(Message2, sizeof(Message2)) != sf::Socket::Done)
        {
                // Error...
        }
        else{
                cout << "Sent message to server" << endl;
        }
       
    // Create the main rendering window
    sf::RenderWindow App(sf::VideoMode(480, 320, 32), "Window");
        const sf::Input& Input = App.GetInput();
    // Start game loop
    while (App.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            // Close window : exit
                        if (Event.Type == sf::Event::Closed){
                                //Player decided to close the program
                                //Check if we've closed the socket yet
                                //If we haven't, close it
                                if(!closedConnection){
                                        Server.Close();
                                        closedConnection = true;
                                }
                App.Close();
                        }
        }

        // Clear the screen (fill it with black color)
        App.Clear(sf::Color(255, 255, 255));

        // Display window contents on screen
        App.Display();
    }
        //We come to the end of the program
        //Check if we've closed the socket yet
        //If we haven't, close it
        if(!closedConnection){
                Server.Close();
                closedConnection = true;
        }
    return EXIT_SUCCESS;
}
 

SERVER:
/************************************************************
SERVER
************************************************************/

#include <iostream>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
using namespace std;

//Entry
int main(){
        sf::SocketTCP Client;
        sf::IPAddress ClientAddress;
        sf::SocketTCP Listener;
        Client.SetBlocking(false); //It honestly makes no difference whether it's true/false, same problem still
        Listener.SetBlocking(false); //It honestly makes no difference whether it's true/false, same problem still
        //Buffer to receive messages
        char Buffer[128];
        //How many messages we've received
        std::size_t Received;
        bool running = true;
        if (!Listener.Listen(4567))
        {
                // Error...
                cout << "Unable to listen on TCP port: 4567" << endl;
        }
        else{
                cout << "Listening on TCP port: 4567" << endl;
        }
        while(running){
                //Waits until a incoming connection arrives
                if (Listener.Accept(Client, &ClientAddress) != sf::Socket::Done)
                {
                        // Error...
                        //cout << "Unable to accept any incoming connections" << endl;
                }
                else{
                        cout << "Accepted a Client!" << endl;
                }
                if (Client.Receive(Buffer, sizeof(Buffer), Received) != sf::Socket::Done)
                {
                        // Error...
                        //cout << "Unable to receive any messages from client." << endl;
                }
                else{
                        cout << "Message: " << Buffer << endl;
                }
        }
}
 
« Last Edit: September 20, 2012, 07:54:42 am by Grimlen »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Server can only receive one message at a time?
« Reply #14 on: September 20, 2012, 07:57:42 am »
I'd like to test your code, but it uses SFML 1.6. Don't you want to upgrade to SFML 2 (which is a much better version anyway)?
Laurent Gomila - SFML developer