Results 1 to 5 of 5

Thread: UDP recv returns -1

  1. #1

    Default UDP recv returns -1

    Hello,

    I'm writing a network game using ClanLib and use the NetSession layer. I use both reliable and unreliable sending of messages and that is where my problem arises.

    As long as I send reliable only, all is fine.

    When I send unreliable however and a client disconnects from the server, the CL_NetSession_Generic::accept_thread() on the server-side is exited due to recv in the accept_udp_socket socket returning -1. In the accept_thread code, a CL_Error is thrown ("CL_Socket: recv failed" or similar) by CL_Socket::recv at this location:


    if (accept_udp_socket.get_read_trigger()->get_flag())
    {
    // Incoming UDP message from client:

    CL_IPAddress from;
    int bytes_available = accept_udp_socket.recv(buffer, msg_size, from);

    dispatch_udp_messege_server(from, bytes_available, buffer);
    }

    Which leads to the accept_thread being terminated and further clients unable to connect from that point on. UDP messages also don't get sent anymore and everything from the networking perspective on the server side is halted. The rest of the server runs fine.

    I found out that when recv returns -1, it means an error on that socket occured. Since in my case this is caused by a disconnect and the disconnect is already propagated through tcp means to the server code, I just catch and ignore the exception inside the CL_NetSession_Generic::accept_thread( ) function and things seem to work fine.

    But that is just a workaround probably. My problems are:

    1. I don't know the architecture of the NetSession enough to be able to say this will work without bad consequences.

    2. My game is open source and when people download and compile ClanLib, they will have a problem because my workaround is not in the package.

    I am using ClanLib 0.8.0 from the package on the site under WindowsXP. I also develop my game under MacOSX and there the problem did not arise so I guess that -1 is sent by Winsock only I guess.

  2. #2
    Administrator Seth's Avatar
    Join Date
    Jul 2002
    Location
    Japan
    Posts
    5,343

    Default

    I think the networking may be in need of some TLC (tender loving care), I'm sort of maintaining the 0.8 version (basically just fixing bugs at this point) but I haven't written anything using networking so I'm sort of in the dark there.

    If you want to switch to using the SVN version and send over patches I think it'd do more good than harm.

    On a side note,

    I think we probably need a few more networking examples/tests to more robustly check if a change broke something or not.

    Any other 0.8 guys using the networking stuff out there?
    Seth A. Robinson
    Robinson Technologies

  3. #3

    Default

    For my project, I switch to RakNet for networking. While I find CL networking has a nicer class and interface design, RakNet does it's job extremely well and works at points where CL fails:

    CL networking has endian issues which are a complete showstopper for me. Though you can set endianness in input and output sources in your local code, they are used internally in CL net when receiving packets and there, no endianness is set (meaning local endianness is assumed). The 0.8.0 networking overview states in a brief comment that little endian is used by default but that is not what the code does. You would need a static flag in input and outputsource that will determine the endianness of all instances (unless overriden). This could be initialized in setup core, while the default argument would still be "local endianness" in order not to break existing code.

    Another thing that was a pain is that when a CL_Socket is destroyed under Windows, the default 0.8.0 release calls a blocking windows select/wait function with a timeout of 60 seconds (!) to "make sure everything needed to be sent got sent" or something. Deleting a socket happens not only when you dispose a NetSession, but also in an unexpected place: When calling NetSession listen, because internally, listen uses the copy constructor of a local socket variable to assign a newly created one to it. This again means a 60 seconds wait though you "just" start a connection.

    In general I don't know whether it makes sense for CL to reinvent the wheel of writing a good and stable network code (the mix of tcp and udp is neither ideal) instead of just saying "use raknet/opentnl/your choice here" for networking.

  4. #4
    Administrator Seth's Avatar
    Join Date
    Jul 2002
    Location
    Japan
    Posts
    5,343

    Default

    On the 60 second time out problem, I think I may have fixed (hacked around?) this in SVN a while ago when I was testing the IRC chat app...

    If you're doing some very heavy/tricky networking things using a separate networking lib might be less work it sounds like. But if CL is ...almost... good enough, please feel free to take a knife to it.

    I thought networking always had to be big endian or it wouldn't work at all. Or is this concerning the payload? Maybe the network class should just be setting the input/output source directly? To keep my file formats compatible between platforms, I do this automatically when saving/loading files through a utility class.
    Seth A. Robinson
    Robinson Technologies

  5. #5

    Default

    When you say bit_stream.output.write_uint32( 12345 );

    Then, if one computer is little and the other is big, they will not get the same result when they read_uint32 from it. So you set it to one endianness, most commonly little since big endian machines are a lot less in the user world.

    This would work, but the problem is that NetSession & Co. don't set endianness when writing their internal packet management stuff. It just fails cross-endian.

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •