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

Author Topic: Call sf::Socket::Disconnect while receiving  (Read 5343 times)

0 Members and 1 Guest are viewing this topic.

AlexAUT

  • Sr. Member
  • ****
  • Posts: 396
    • View Profile
Call sf::Socket::Disconnect while receiving
« on: October 25, 2014, 05:47:36 pm »
Is the behaviour defined when I call disconnect from a Socket which is currently blocking a other thread because of receive? (Blocking sockets)

In my experience the receive call will return instantly with no data received, but is this behaviour defined, or just implementation luck on OS/Driver level?


AlexAUT
« Last Edit: October 25, 2014, 05:49:43 pm by AlexAUT »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Call sf::Socket::Disconnect while receiving
« Reply #1 on: October 25, 2014, 06:39:52 pm »
While most operating systems have internal locking on sockets, it is not guaranteed everywhere. Because of that, you will always have to live with the possibility that some smart person is able to modify the Linux kernel and remove the locks if they find it appropriate for their distribution. Also, while simultaneous sending and receiving might not be a problem, because of the nature of TCP, disconnecting and closing (which SFML currently implicitly does) the socket on another thread while you are simultaneously blocking on a receive operation might cause undefined behaviour. That is already disregarding the fact that TCP has a well-defined connection tear-down mechanism that SFML does not respect, you don't have to make matters worse ;).

If you ask me, if you have to make this kind of consideration, you should reconsider the design of your system. Having to rely on operating system side effects to synchronize your own code is never a good idea. It might seem simple to understand now, but at some point down the road, it will become so complex that you will not know why things don't work as intended any longer, and waste a lot of time debugging. Instead, you should think about making synchronization more explicit between threads. Have a single thread take exclusive care of communication on a socket. Everything that happens to that socket will happen on that thread and no other. This way you don't have to distribute code concerning the same matter over multiple sites and even threads.

This design is probably not scalable, considering that you currently have a thread per socket, but that is a story for another time...
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

AlexAUT

  • Sr. Member
  • ****
  • Posts: 396
    • View Profile
Re: Call sf::Socket::Disconnect while receiving
« Reply #2 on: October 26, 2014, 02:29:05 pm »
Thanks Binary1248 for your helpful answer!

Have a single thread take exclusive care of communication on a socket. Everything that happens to that socket will happen on that thread and no other. This way you don't have to distribute code concerning the same matter over multiple sites and even threads.

But this implies that I have to use a non-blocking socket(or a selector) in the thread right?



AlexAUT

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Call sf::Socket::Disconnect while receiving
« Reply #3 on: October 27, 2014, 03:30:31 pm »
But this implies that I have to use a non-blocking socket(or a selector) in the thread right?
I don't know what your code looks like, but since you currently block on a receive in one thread, I assumed that receiving would be the only thing you had to do. If you have to both send and receive, then yes, using a selector would be better and allow you to control all operations within a single thread. However, bear in mind that having too many selectors is also not such a good idea. Selectors were designed to multiplex a large number of sockets into a single point for you to query, thus having a single selector for many sockets will generally perform better than having a selector per socket. This is made even worse by the fact that SFML still relies on the ancient POSIX select(). It normally has constant complexity, but to achieve that it also has a fixed maximum size on many systems (commonly 1024 on UNIX systems). This means that your frame time will increase linearly by the number of selectors you have to poll.

The cleanest solution would be to have a single selector handling all your sockets, and as soon as it sees there is work to be done, dispatch a message to a worker thread to handle that work. SFML doesn't support polling for send-readiness, so this will only work for receiving, but it should suffice if you don't have to send HUGE chunks of data. There are many places where SFML networking can be improved, but let's save it for SFML 3 ;).
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

AlexAUT

  • Sr. Member
  • ****
  • Posts: 396
    • View Profile
Re: Call sf::Socket::Disconnect while receiving
« Reply #4 on: November 03, 2014, 08:59:22 pm »
Thanks for the great answer,
I spent some time over the last week and implemented the way you suggested (dispatch messages to a worker thread) and it works great. (Created a little chat system for my university mates ~50people, just to get a feeling for network things)


AlexAUT