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

Author Topic: TcpSocket::receive(Packet) doesn't work  (Read 3211 times)

0 Members and 2 Guests are viewing this topic.

Guillaume21

  • Newbie
  • *
  • Posts: 9
    • View Profile
TcpSocket::receive(Packet) doesn't work
« on: August 11, 2013, 11:58:44 am »
Hello,

It's the first time I use the networking part of SFML and I found out the class "Packet", which looks nice to send and receive data easily.

However, I never receive ANY data when I do something like:
TcpListener tcpListener;
TcpSocket mapControllerSocket;

tcpListener.setBlocking(false);

if (tcpListener.listen(MAP_CONTROLLER_COMMUNICATION_PORT) != Socket::Status::Done)
{
                MessageBoxA(window.getSystemHandle(), "Cannot attach to Map Controller, check if port 40235 is not blocked or already in use.\r\n\r\nTerminating...", MAP_VIEWER_WINDOW_TITLE.c_str(), MB_ICONERROR);
                return EXIT_FAILURE;
}


time_t startTime = time(NULL);

while (startTime + 10 >= time(NULL))
{
        if (tcpListener.accept(mapControllerSocket) == Socket::Status::Done)
                break;
}

if (mapControllerSocket.getRemoteAddress().toInteger() == 0)
{
        MessageBoxA(window.getSystemHandle(), "Cannot attach to Map Controller, try to restart the program.\r\n\r\nTerminating...", MAP_VIEWER_WINDOW_TITLE.c_str(), MB_ICONERROR);
        return EXIT_FAILURE;
}


Packet packet;
mapControllerSocket.receive(packet);

// Stuff...
It stays blocked (no exception, just waiting) at line mapControllerSocket.receive(packet);


However, when I replace the last 2 lines with:

byte *buffer = new byte[100];
size_t rcvLen = 0;
mapControllerSocket.receive(reinterpret_cast<void*>(buffer), 100, rcvLen);
It works fine! I receive my data as expected.

I'd really like to use the Packet class so... do you know what's the problem?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TcpSocket::receive(Packet) doesn't work
« Reply #1 on: August 11, 2013, 12:50:56 pm »
Please show a complete and minimal example that reproduces the problem, both client and server.
Laurent Gomila - SFML developer

Guillaume21

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: TcpSocket::receive(Packet) doesn't work
« Reply #2 on: August 11, 2013, 01:24:25 pm »
The client is written in C# :

using System.Net.Sockets;

namespace Control.Communication
{
    class MapViewer
    {
        private Socket _mapViewerSocket;



        public MapViewer()
        {
            _mapViewerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
       

        public bool Attach(int communicationPort)
        {
            try
            {
                _mapViewerSocket.Connect("127.0.0.1", communicationPort);
            }

            catch
            {
                return false;
            }

            return true;
        }

        public bool SendByte(byte val)
        {
            try
            {
                _mapViewerSocket.Send(new byte[] {val});
            }

            catch
            {
                return false;
            }

            return true;
                }
    }
}
 

And then :
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
        _mapViewer = new MapViewer();

        if (!_mapViewer.Attach(MapViewerCommunicationPort)) // 40235
        {
                MessageBox.Show("Cannot attach to Map Viewer, try to restart the program.\r\n\r\nTerminating...", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit();
        }


        _mapViewer.SendByte((byte)1);
}


It's a little bit messy but it's just a test project.


The server (C++/SFML) :
int main(int argc, char *argv[])
{
        const string MAP_VIEWER_WINDOW_TITLE = "Map Viewer";
        const int MAP_CONTROLLER_COMMUNICATION_PORT = 40235;


        TcpListener tcpListener;
        TcpSocket mapControllerSocket;
       
        tcpListener.setBlocking(false);



        RenderWindow window(VideoMode(1200, 800, 32), MAP_VIEWER_WINDOW_TITLE, Style::Close);
        window.setFramerateLimit(60);


        /* Connect to Map Controller */

        if (tcpListener.listen(MAP_CONTROLLER_COMMUNICATION_PORT) != Socket::Status::Done)
        {
                MessageBoxA(window.getSystemHandle(), "Cannot attach to Map Controller, check if port 40235 is not blocked or already in use.\r\n\r\nTerminating...", MAP_VIEWER_WINDOW_TITLE.c_str(), MB_ICONERROR);
                return EXIT_FAILURE;
        }


        time_t startTime = time(NULL);

        while (startTime + 10 >= time(NULL))
        {
                if (tcpListener.accept(mapControllerSocket) == Socket::Status::Done)
                        break;
        }

        if (mapControllerSocket.getRemoteAddress().toInteger() == 0)
        {
                MessageBoxA(window.getSystemHandle(), "Cannot attach to Map Controller, try to restart the program.\r\n\r\nTerminating...", MAP_VIEWER_WINDOW_TITLE.c_str(), MB_ICONERROR);
                return EXIT_FAILURE;
        }



        Packet packet;
        mapControllerSocket.receive(packet);
       
        while (window.isOpen())
        {
                ...
        }
       
       
        return EXIT_SUCCESS;
}


I think I have the same problem (french): http://fr.sfml-dev.org/forums/index.php?topic=8803.0


Actually, it seems the socket receives the data, but won't copy them to a Packet:


I actually sent 4 bytes from my C# client.
« Last Edit: August 11, 2013, 01:27:00 pm by Guillaume21 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TcpSocket::receive(Packet) doesn't work
« Reply #3 on: August 11, 2013, 02:01:23 pm »
sf::Packet has its own little protocol, you can't send raw bytes and receive them as a sf::Packet, everything will be messed up.
Laurent Gomila - SFML developer

Guillaume21

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: TcpSocket::receive(Packet) doesn't work
« Reply #4 on: August 11, 2013, 02:09:15 pm »
Oh! I didn't know.
So if I want to use sf::Packet in my server I must use it in my client as well? I must use the .NET binding of SFML?

Thank you!

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: TcpSocket::receive(Packet) doesn't work
« Reply #5 on: August 11, 2013, 02:17:14 pm »
If you want to implement the sf::Packet mechanism in your C# code, prefix your data with their length in a 4-byte length field.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: TcpSocket::receive(Packet) doesn't work
« Reply #6 on: August 11, 2013, 03:15:16 pm »
Quote
Oh! I didn't know.
It's in the tutorial.

Quote
So if I want to use sf::Packet in my server I must use it in my client as well? I must use the .NET binding of SFML?
There's no .Net binding of sfml-network. Your only option is to reimplement the sf::Packet protocol, which is very simple as binary1248 described. Additionnally, all primitive types are encoded in network byte order (big endian), so you will most likely have to byte-swap them.
Laurent Gomila - SFML developer