Sign in to follow this  
MeshMan

UDP Clients

Recommended Posts

MeshMan    134
Hi guys, I'm writing a UDP network library (for learning purposes) and I would like to know what the best way of storing unique connected clients is. At the moment, I'm just using the SOCKADDR from when the client first starts sending packets. Does that suffice? Thanks, MeshMan

Share this post


Link to post
Share on other sites
markr    1692
Yes, a sockaddr should be fine. More specifically, a struct sockaddr_in

Even more specifically, you can also ignore the sa_family member, because it will always be the same.

You should of course always check on an incoming packet, that it's either the start of a new session, or it's coming from an IP address (well, sockaddr_in anyway) that you recognise as part of an existing session.

There are also heaps of other checks you need to do to ensure that packets are not being spoofed and/or are arriving in the appropriate order.

Lots of weird things can happen, including packets arriving in the wrong state because of network congestion.

Mark

Share this post


Link to post
Share on other sites
MeshMan    134
My network library is almost up to speed with ENet (apart from the voice stuff which I'm gonna add soon with the help of FMod :)) but what I'm findins is that I keep repeatedly getting a WSAECONNRESET error code from the recvfrom() on my listening server socket and according to MSDN, I don't know what it means by ICMP Port Unreachable. How should I react to this error?
It only happens when a client quits the server and the server doesnt know he has disconnected, and then he connects from the same machine..

Share this post


Link to post
Share on other sites
doho    378
Look for these links about WSAECONNRESET
gamedev thread
MSDN

Here is some source that I used to fix the problem.

void Socket::DisableConnResetError()
{
DWORD NewBehaviour;
OSVERSIONINFOEX Info;


// get information about os
WinUtilities::GetOSInfo(&Info);

// platform is win9x or winnt?
if(Info.dwMajorVersion <= 4)
{
return;
}

// platform is win2k with service pack <= 1 installed?
if(Info.dwMajorVersion == 5 && Info.dwMinorVersion == 0 && Info.wServicePackMajor <= 1)
{
return;
}

// platform is either win2k with service pack >= 2 or winxp, so discard WSAECONNRESET errors
NewBehaviour = 0;

if(ioctlsocket(m_Socket, _WSAIOW(IOC_VENDOR, 12), &NewBehaviour) == SOCKET_ERROR)
{
throw Exception(true, "unable to set SIO_UDP_CONNRESET socket option");
}
}

Share this post


Link to post
Share on other sites
markr    1692
I was not aware that Windows actually reported UDP errors in this way, I thought it just dropped them.

Anyway, it's not clear to me how to determine the address of the host which generated the ECONNREFUSED on a UDP socket. Perhaps it fills in the from and fromlen pointers when you call recvfrom() even in this error condition. Presumably it must, otherwise it would be useless on a socket used to service multiple clients. Some research is obviously required to find this out.

If you are not interested, presumably it's safe to ignore the ECONNREFUSED and just call recvfrom again until you get a packet of data.

Mark

Share this post


Link to post
Share on other sites
MeshMan    134
Quote:
Original post by markr
You should of course always check on an incoming packet, that it's either the start of a new session, or it's coming from an IP address (well, sockaddr_in anyway) that you recognise as part of an existing session.


Ok. I've reacted to the WSAECONNRESET error by getting the SOCKADDR_IN from the recvfrom() and comparing it to already connected players then booting that client off. All works.

Share this post


Link to post
Share on other sites
markr    1692
If by "booting the client off", you mean, just deleteing their entry from the connected clients table (after doing any local cleanup), yes fine.

I can't see any use for sending any more packets to a client after it's got a CONNREFUSED error.

Mark

Share this post


Link to post
Share on other sites
MeshMan    134
Yes. Not sending anymore packets to that client, just deleting their entry from my connected list.

What I still don't understand is that if I'm not sending any packets to that socket (or am I?), how come I repeatedly keep getting the WSAECONNRESET error on the socket.

Am I right in thinking that if I try and send a packet to an invalid address, it SOMEHOW?? comes back as a WSAECONNRESET error on my listening socket?

Meshy.

Share this post


Link to post
Share on other sites
markr    1692
I believe these errors happen if a remote host or an intermediate router sends back an ICMP unreachable message for that UDP ip adress / port number.

Because it's all a bit asynchronous, it might not come back immediately, you could get one later.

The remote host should send a maximum of one unreachable per UDP datagram received, I would have thought. Moreover, it should apply rate-limiting in case it gets bombarded with invalid UDP packets (Although I think Windows does not implement this).

So unless you're continuing to bombard the host with udp even after it's stopped listening, you shouldn't keep getting these messages back.

Of course any messages that were in transit or queued, may cause responses for that host. So you might get a few. But they should stop after you stop sending to that host.

Are you sure you're processing them on behalf of the right host?

Have you tried it on a lan with several real hosts and with a packet logger watching to see what's happening?

Mark

Share this post


Link to post
Share on other sites
MeshMan    134
Thanks for getting back Mark. I'm in the middle or more testing.
I've never used a packet logger before, any good free ones out there you could name for me?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this