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

Author Topic: UdpSocket.receive() sets passed Ip and port to 0.  (Read 10859 times)

0 Members and 1 Guest are viewing this topic.

KRS

  • Newbie
  • *
  • Posts: 19
  • The burning you feel?
    • View Profile
    • Email
UdpSocket.receive() sets passed Ip and port to 0.
« on: March 19, 2021, 08:48:54 pm »
Hello! I'm sorry my english can be bad sometimes. I'm having a problem, when
IpAddres ip;
unsigned int port;
objects passed to a
udpSocket.receive(packet, ip, port);
turns out to be == 0
It happens in this part of code(this code lives in while(true) loop)

ClientsVec stores clients with their  ip, UdpSocket and port, so that thay can be used further to send and receive data. All the sockets are
.setBlocking(false)
.
As you can see before hitting the line with
receive()
ip is valid.
Than
.receive()
returns whatever but not
Socket::Status::Done
because nothing was sent, so that body stays not executed. And all above is undertandable by me.
But as soon as
.receive()
gets executed:


Also I understand that receive() takes as parameters adresses of Ip and port variables -
.receive(&packet, &Ip, &port);
so it can do whatever it wants with these var-s.
But I can not understand what conditions makes this method reset these variables, and why it happens. Also source code of a UdpSocket is too hard for my to understand, because I'm not experienced.
I will be really happy if someone will give me some advice :)




eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: UdpSocket.receive() sets passed Ip and port to 0.
« Reply #1 on: March 19, 2021, 09:37:35 pm »
If nothing is received, you should not depend on the values "returned" by receive.

SFML's source really isn't that hard to understand. You wrote the code you posted, so you should easily be able to understand the following code from the UdpSocket::receive implementation:

    // First clear the variables to fill
    received      = 0;
    remoteAddress = IpAddress();
    remotePort    = 0;

Followed by an early exit before setting the IP address or port:
    // Check for errors
    if (sizeReceived < 0)
        return priv::SocketImpl::getErrorStatus();
« Last Edit: March 19, 2021, 09:39:36 pm by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

KRS

  • Newbie
  • *
  • Posts: 19
  • The burning you feel?
    • View Profile
    • Email
Re: UdpSocket.receive() sets passed Ip and port to 0.
« Reply #2 on: March 19, 2021, 10:02:23 pm »
if (sizeReceived < 0) return priv::SocketImpl::getErrorStatus();
Does that means that if size of received information is < than 0 bytes (which is error) then method brakes before filling ip and port variables with correct values?

But than I would really wanted to know in wich cases sizeReceived  can be < 0?

// Receive a chunk of bytes
    priv::SocketImpl::AddrLength addressSize = sizeof(address);
    int sizeReceived = recvfrom(getHandle(), static_cast<char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
These looks like answer but it looks really scary for me.

Also I feel that maybe I somehow insulted you or your work in my post, just to make clear, I got no disrespect to you or your code, I'm just not that expirienced in programming in general.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: UdpSocket.receive() sets passed Ip and port to 0.
« Reply #3 on: March 19, 2021, 10:46:48 pm »
The if statement just means that you didn't receive anything, which can have different meanings, but since you're in a non-blocking mode, most of the time the socket will not have received anything.

Put simply: If the socket doesn't return sf::Status::Done then the IP and Port will be reset.

You might be interested to read about socket selectors, I think that would fit your setup better.

I somehow insulted you or your work in my post, just to make clear, I got no disrespect to you or your code, I'm just not that expirienced in programming in general.
Don't worry, I didn't read it that way. Maybe my formulation was a bit direct as well. Communication is, especially if it's just text based. ;D
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

KRS

  • Newbie
  • *
  • Posts: 19
  • The burning you feel?
    • View Profile
    • Email
Re: UdpSocket.receive() sets passed Ip and port to 0.
« Reply #4 on: March 19, 2021, 11:04:36 pm »
You know, I done my client server architecture using selector, such a usefull thing, and everything worked great, but you see: I wanted my server to receive at any time, as soon as possible(and for this job selector is perfect) but also I wanted my server to send data to every client using some time rate, for example - every 100 milliseconds. So you see, in server's while(true) cycle if I'm using selector to receive - its blocking my sendings. Of course I can set selector wait time something like 10 milliseconds, so that sendings can come through.... But wait, can selector be not blocking? Maybe I'just missed that selector actually can to not block execution?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: UdpSocket.receive() sets passed Ip and port to 0.
« Reply #5 on: March 20, 2021, 10:44:00 am »
Yes, you can use non-blocking sockets with a socket selector.

See also this helpful FAQ answer.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

KRS

  • Newbie
  • *
  • Posts: 19
  • The burning you feel?
    • View Profile
    • Email
Re: UdpSocket.receive() sets passed Ip and port to 0.
« Reply #6 on: March 20, 2021, 12:54:23 pm »
Hey, so I finally understand - when I'm receieving something from non-blocking socket, I'm passing temporary Ip and port variables.
IpAddress tempIp = serverIp;
Uint16 tempPort = dataServerPort;
if (dataSocket.receive(rPacket, tempIp, tempPort) == Socket::Status::Done)

Thank you very much for help, cant wait for 2.6.0 ;D