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

Author Topic: Sending "types" of packet via UDP  (Read 9236 times)

0 Members and 1 Guest are viewing this topic.

wilbefast

  • Newbie
  • *
  • Posts: 31
    • View Profile
    • http://wilbefast.com
Sending "types" of packet via UDP
« on: September 09, 2010, 02:07:38 pm »
This is probably a very stupid question, but bear with me.

I'm trying to build my first ever network game. For this I need to be able to send many different kinds of "message" between the computers. For instance:
- connection request
- you have x time left before you lag-out
- object y is at position z
- object t has been created at position u
- etc

So I don't know what my packet will contain until I open it, but until I open it I don't know what it will contain  :(
My idea was to give each packet a sort of "header" which lets the receiver know how to open it. The header would always be, say, a short unsigned integer.

I know this is possible if I'm just sending bytes but it would be rather fiddly. Is there a way of implementing this kind of stuff with SFML packets?

Thanks,


William

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sending "types" of packet via UDP
« Reply #1 on: September 09, 2010, 02:25:49 pm »
Sure, there's no problem
Code: [Select]
// sending
sf::Packet packet;
packet << header << ... specific data ... ;
socket.Send(packet);


Code: [Select]
// receiving
sf::Packet packet;
socket.Receive(packet);

sf::Uint8 header;
packet >> header;

switch (header)
{
    case ConnectionRequest:
        packet >> ... specific data ...;
        connect(...);
        break;

    case MoveObject:
        packet >> ... specific data ...;
        moveObject(...);
        break;

    ...
}
Laurent Gomila - SFML developer

wilbefast

  • Newbie
  • *
  • Posts: 31
    • View Profile
    • http://wilbefast.com
Sending "types" of packet via UDP
« Reply #2 on: September 09, 2010, 02:54:16 pm »
Thanks! That's really helpful  :D

wilbefast

  • Newbie
  • *
  • Posts: 31
    • View Profile
    • http://wilbefast.com
Sending "types" of packet via UDP
« Reply #3 on: September 09, 2010, 05:51:43 pm »
Hmmm... :?

I've been able to get my the two machines (one real, one virtual) connected, but sending packets doesn't seem to be working somewhere along the line...

192.168.56.1 is the address of the virtual machine (192.168.56.101 is the address of the real one) in the virtual network. I've managed to send and receive via UDP, but TCP doesn't seem to like me very much. What's wrong with this picture :(

Code: [Select]
#include "lobby.h"

using namespace std;

int lobby_join(sf::RenderWindow& window)
{
    bool connected = false;

    //Get server IP Address
    sf::IPAddress serverIP = "192.168.56.1";

    //Load Font
    sf::Font font;
    if(!font.LoadFromFile("content/fonts/Courier_New.ttf"))
        cout << "Unable to load font\n";

    //Create String
    sf::String message("attempting to connect:\nPress 'Esc' to cancel\n", font, 50);
    message.SetColor(sf::Color(0, 0, 0));
    message.SetPosition(32,32);

    //Create socket: pipeline to server
    sf::SocketTCP server;
    server.SetBlocking(false);

    //Check the validity of the address
    if(!serverIP.IsValid())
        cout << serverIP << " is invalid\n";

    //create buffers
    sf::Packet packet;
    sf::Uint8 header;

    //Create Event handler called 'event'
    sf::Event event;

    //start the main loops
    bool running = true;
    while(running)
    {
        //Read each Event, store in 'event' and treat
        while (window.GetEvent(event))
        {
            switch (event.Type)
            {
                //Window closed
                case sf::Event::Closed:
                    running = false; break;
                //Key press
                case sf::Event::KeyPressed:

                    switch (event.Key.Code)
                    {
                         //ESCAPE key
                        case (sf::Key::Escape):
                            running = false; break;
                        //all other cases
                        default:
                            send(PING,server);
                            cout << "Sent ping to " << serverIP << endl;
                            break;
                    }
                    break;

                //all other cases
                default: break;
            }
        }

        //attempt to connect to the address if not already connected
        if(!connected)
        {
            if (server.Connect(PORT, serverIP) == sf::Socket::Done)
            {
                cout << "Connected to server " << serverIP << endl;
                connected = true;
                message.SetText("Connected: Waiting\nfor server to start\nPress 'Esc' to disconnect\n");
            }
        }
        //try to retrieve a packet from the host if connected
        else if (server.Receive(packet) == sf::Socket::Done)
        {
            //interpret packet based on header
            packet >> header;
            switch(header)
            {
                //
                case PLAY:
                    printf("The host has started the game\n");
                    //play(...);
                    break;

                //host has left
                case QUIT:
                    printf("The host has left the lobby\n");
                    running = false; break;

                default:
                    printf("Unknown packet type %d received\n",header); break;
            }
        }

        //Clear the Windows
        window.Clear(sf::Color(0, 200, 0));

        //Draw the the message
        window.Draw(message);

        //Redraw the Window
        window.Display();

    }

    //Close the socket
    server.Close();

    printf("Stopped joining\n\n");
    return EXIT_SUCCESS;
}

int lobby_host(sf::RenderWindow& window)
{
    bool connected = false;

    //Load Font
    sf::Font font;
    if(!font.LoadFromFile("content/fonts/Courier_New.ttf"))
        cout << "Unable to load font" << endl;

    //Create String
    sf::String message("Waiting for connections:\nPress 'Enter' to start\nPress 'Esc' to cancel", font, 50);
    message.SetColor(sf::Color(0, 0, 0));
    message.SetPosition(32,32);

    //Create server socket
    sf::SocketTCP server;
    server.SetBlocking(false);

    // Listen to a port for incoming connections
    if (server.Listen(PORT))
        std::cout << "Listening to port " << PORT << ", waiting for connections" << std::endl;
    else
        std::cout << "Can't listen to port " << PORT << std::endl;

    //Create client socket
    sf::IPAddress clientIP;
    sf::SocketTCP client;

    //Create buffers
    sf::Packet packet;
    sf::Uint8 header;

    //Create Event handler called 'event'
    sf::Event event;

    //start the main loops
    bool running = true;
    while(running)
    {
        //Read each Event, store in 'event' and treat
        while (window.GetEvent(event))
        {
            switch (event.Type)
            {
                //Window closed
                case sf::Event::Closed:
                    running = false; break;
                //Key press
                case sf::Event::KeyPressed:

                    switch (event.Key.Code)
                    {
                         //ESCAPE key
                        case (sf::Key::Escape):
                            send(QUIT,client);
                            running = false;
                            break;
                        //RETURN key
                        case (sf::Key::Return):
                            send(PLAY,client);
                            ///FIXME
                            //play(...);
                            break;

                        //all other cases
                        default:
                            send(PING,client);
                            printf("Sent ping to client\n");
                            break;
                    }
                    break;

                //all other cases
                default: break;
            }
        }

        //Check for connections if not already connected
        if (connected == false)
        {
            if (server.Accept(client, &clientIP) == sf::Socket::Done)
            {
                message.SetText("Client connected:\nPress 'Enter' to start\nPress 'Esc' to cancel\n");
                std::cout << "Client connected : " << clientIP << std::endl;
            }
        }
        //Check for packets if connected
        else if (client.Receive(packet) == sf::Socket::Done)
        {
            //interpret packet based on header
            packet >> header;
            switch(header)
            {
                default:
                    printf("unkown packet type %d received\n", header);
                    break;
            }
        }

        //Clear the Windows
        window.Clear(sf::Color(0, 0, 200));

        //Draw the the message
        window.Draw(message);

        //Redraw the Window
        window.Display();

    }

    //Close the sockets
    server.Close();
    client.Close();

    printf("Stopped hosting\n\n");
    return EXIT_SUCCESS;
}

void send(int message, sf::SocketTCP target)
{
    sf::Packet packet;
    packet << (sf::Uint8) message;
    target.Send(packet);
}


PS - I see you are from France!

Feel free to reply in French if you want - I've been learning for 14 years and have been studying Informatique at Montpellier for the last 2  8)

I like writing my comments in English though...


William

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sending "types" of packet via UDP
« Reply #4 on: September 09, 2010, 06:26:01 pm »
I don't see anything wrong in your code.

You can try with blocking sockets and see if it works better. You can also try to connect to localhost, to make sure that your network environment is not involved in the bug.

Quote
Feel free to reply in French if you want

This is an english forum, so we'll stick to english so that other users can understand the discussion ;)
Laurent Gomila - SFML developer

Mindiell

  • Hero Member
  • *****
  • Posts: 1261
    • ICQ Messenger - 41484135
    • View Profile
Sending "types" of packet via UDP
« Reply #5 on: September 10, 2010, 08:42:01 am »
Code: [Select]
int lobby_host(sf::RenderWindow& window)
{
    ...
    bool connected = false;
    ...
    //Check for connections if not already connected
    if (connected == false)
    {
        if (server.Accept(client, &clientIP) == sf::Socket::Done)
        {
            message.SetText("Client connected:\nPress 'Enter' to start\nPress 'Esc' to cancel\n");
            std::cout << "Client connected : " << clientIP << std::endl;
        }
    }
    ...

Maybe try to change the connected boolean to true here ?  :wink:
Mindiell
----

wilbefast

  • Newbie
  • *
  • Posts: 31
    • View Profile
    • http://wilbefast.com
Sending "types" of packet via UDP
« Reply #6 on: September 10, 2010, 08:31:55 pm »
Good find :D

Unfortunately it doesn't fix the problem :( I wonder why it should work for UDP and normal command-line pings, just not for TCP... there must be something wrong with the code somewhere :?

Mindiell

  • Hero Member
  • *****
  • Posts: 1261
    • ICQ Messenger - 41484135
    • View Profile
Sending "types" of packet via UDP
« Reply #7 on: September 13, 2010, 09:13:33 am »
Give us the minimal code (see my signature) of the client and the server. I could test it here.
Mindiell
----

wilbefast

  • Newbie
  • *
  • Posts: 31
    • View Profile
    • http://wilbefast.com
Sending "types" of packet via UDP
« Reply #8 on: September 14, 2010, 10:34:06 am »
Thanks Mindiell. Okay so... minimum code. You're asking me to chop up my babies!?
This should compile with the code at the top of the file. Make sure you changer SERVER to the ip you're connecting to:

http://pastebin.com/QD9cJukj

Okay, so there's still a lot there... let me know if it's not "minimum" enough :oops:

edit: yeah - it's definately a problem with my code or with the packets: I did a test of my network setup using the example code from this page

http://www.sfml-dev.org/tutorials/1.6/network-sockets.php

and everything works fine for TCP messages as well as UDP ones.

Mindiell

  • Hero Member
  • *****
  • Posts: 1261
    • ICQ Messenger - 41484135
    • View Profile
Sending "types" of packet via UDP
« Reply #9 on: September 16, 2010, 09:37:17 am »
Arg !

I have to switch from SFML 2 to SFML 1.7 to test your code :/
I'll give you more infos...
Mindiell
----

wilbefast

  • Newbie
  • *
  • Posts: 31
    • View Profile
    • http://wilbefast.com
Sending "types" of packet via UDP
« Reply #10 on: September 16, 2010, 01:39:07 pm »
Sorry  :? I tend to use stable builds when I can. What's changing for 2.0?

Mindiell

  • Hero Member
  • *****
  • Posts: 1261
    • ICQ Messenger - 41484135
    • View Profile
Sending "types" of packet via UDP
« Reply #11 on: September 20, 2010, 08:46:06 am »
Gasp, a lot of things. But 2.0 is almost stable, nothing very difficult to use. The only thing is that Laurent is not releasing it because he wants to finish it properly before.
Mindiell
----