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

Author Topic: UDPSocket permanently goes into error (on send) after Status::notReady receive  (Read 5109 times)

0 Members and 1 Guest are viewing this topic.

vvolfster

  • Newbie
  • *
  • Posts: 11
    • View Profile
Hi all,

I have run into a few obstacles while coding in SFML but this one has been driving me crazy. After many hours of reading everything I could find through google and SFML 2.1 docs, I have decided to let out a desperate plea for help.

The goal here is for the client to spam "hello_server" until it gets a response from the server in recvMsg(). However, after it runs recvMsg(), the socket Status is constantly be sf::Socket::Error. What is weird is that if I don't run the recvMsg(), it will do exactly what I intended it to. Will spam "hello_server" successfully.

On recvMsg(), I get sf::Socket::NotReady obviously because the server is not there to respond.

Here is my code:
void mainLoop()
    {
        port = 12345;
        while(gameWindow->isOpen())
        {
            sf::Event event;
            while(gameWindow->pollEvent(event))
            {
                if(event.type == sf::Event::Closed)
                {
                    cout << "closing window\n";
                    gameWindow->close();
                }
            }
            logic();
            draw();
        }
    }

void logic()
    {
        playButton.update();
        socket.setBlocking(false);
        if(!handshakeSuccess)
        {
            const char msg[] = "hello_server";

            int sockStatus = socket.send(msg,sizeof(msg),serverIp, 50001);
            if     (sockStatus == sf::Socket::Done)                  std::cout << "Sending Hello Server!\n";
            else if(sockStatus == sf::Socket::NotReady)              std::cout << "Send socket not ready\n";
            else if(sockStatus == sf::Socket::Disconnected)          std::cout << "Send socket disconnected\n";
            else if(sockStatus == sf::Socket::Error)                 std::cout << "Send socket error\n";

            recvMsg();
        }
    }

void recvMsg()
    {
        char inMsg[1024];
        std::size_t received;
        int sockStatus = socket.receive(inMsg,sizeof(inMsg),received,serverIp,port);

        if(sockStatus == sf::Socket::Done)
        {
            std::cout << "message received : " << inMsg << endl;
            handShakeSuccess = true;
        }
}
 

Any help is appreciated. Thanks.
« Last Edit: July 22, 2014, 03:53:44 pm by vvolfster »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
You should not reuse the serverIp variable for both send and receive. An unsuccessful receive may reset it, therefore any subsequent use of it will fail.

On a side note, don't call setBlocking hundred times per seconds. Do it once when you create the socket.
Laurent Gomila - SFML developer

vvolfster

  • Newbie
  • *
  • Posts: 11
    • View Profile
Thank you for your prompt reply. setBlocking(false) was being called only once in another function but I pasted it there to make sure others knew it was called.

You were right though it wasn't just the ipAddress. After adding a temp unsigned int as the receiving port, it started running just fine. I wonder why that is :S

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Because in case of an unsuccessful receive, SFML prefers to reset the sender port and ip, instead of leaving them untouched.
Laurent Gomila - SFML developer

vvolfster

  • Newbie
  • *
  • Posts: 11
    • View Profile
ahh ok, I see. I am kind of new to adding a multiplayer component to my game. What would you suggest is the best way to go about it? I was thinking having a tcp connection so that the client/server know they are connected and then using udp to send data back and forth. Does that seem like a good idea.

I also ran into some troubles with sf::Text but I will post a question about that in the appropriate thread if I can't figure it out on my own. It was crashing a lot whenever I tried to draw it or .getlocalbounds().

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
You should stick to TCP, and use UDP only if really needed.
Laurent Gomila - SFML developer

vvolfster

  • Newbie
  • *
  • Posts: 11
    • View Profile
Since the game is gonna be very real-time, I think I should use UDP . From what I recall, using TCP will halt the stream of incoming data if a segment is lost and wait until it is resent from the source (to simulate ordered delivery of data). That seems very undesirable unless of course I'm mistaken.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Yes, if you actually need this real-time scenario and are able to tolerate packet loss, UDP can be meaningful. But don't forget that you have to implement your own layer of reliability (acknowledgement, retransmission, ordering, duplicate removal), which is not trivial. If this is your first network program, starting with TCP might be a good idea.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Quote
But don't forget that you have to implement your own layer of reliability (acknowledgement, retransmission, ordering, duplicate removal)
UDP is used when you don't need all that stuff. If you do, then TCP already does it.

A typical use of UDP is data that don't need to be ordered nor complete, like an entity position. If you lose one packet then the next one will arrive a few milliseconds after so it's not a big deal.
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
A typical use of UDP is data that don't need to be ordered nor complete, like an entity position. If you lose one packet then the next one will arrive a few milliseconds after so it's not a big deal.
Yes, but this does not apply to all information exchanged over the network. There will still be messages that have to be acknowledged because their arrival is crucial to the logic. And they can be rare enough that the overhead of a separate TCP connection does not pay off.

UDP allows the developer to selectively decide what reliability measures to implement, and for which messages, while TCP categorically does it for all exchanged data.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Hmm I don't know if there's an overhead to have a separate TCP connection which is only used for critical data. This may be a relevant strategy.

Anyway, personnally I'd go first with the most simple solution, one that doesn't require to write tons of extra code to ensure reliability / ordering / etc. and then see what I really need to change or improve based on feedback.
Laurent Gomila - SFML developer