J
Jason
I am working on an asynchronous UDP socket server platform, and I am
running into what appears to be a common problem but I have not found
a good answer yet.
If this was TCP, when the routine EndReceiveData() is called back
(after making a connection and receiving data) you can access the IP
of the remote host by
EndPoint ep = sock.RemoteEndPoint;
Where this would be useful is UDP, where you don't have a connection
established and you actually need to know the IP address where to send
data.
So, in a UDP synchronous setup, you can write code like this
Receive()
{
IpEndPoint ipep = new IpEndPoint(IPAddress.Any,10000);
EndPoint ep = (EndPoint)ipep;
//When this returns, ipep, will now contain the value of the
RemoteEndPoint.
sock.ReceiveFrom(buffer, ref ep);
//Now you can send data back to that computer
sock.SendTo(buffer, ep);
}
So far so good. You can detect who sent the packet and you can reply
back to them. Easy enough.
But once you move to asynchronous, this doesn't work anymore
BeginReceive()
{
IpEndPoint ipep = new IpEndPoint(IPAddress.Any,10000);
EndPoint ep = (EndPoint)ipep;
//When this returns, ipep, will now contain the value of the
RemoteEndPoint, right?
sock.BeginReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref ep, new
AsyncCallback(OnDataReceived), sock);
}
OnDataReceived(IAsyncResult asyn)
{
Socket sock = (Socket)asyn.AsyncState;
int iRx = sock.EndReceive(asyn);
.... ... ...
}
In this case, you can look at sock.RemoteEndPoint but it will throw an
exception. The argument I hear for this is that this is
connectionless and you don't ever get this, but in the syncronous
example above you DO get this with UDP.
If you pass in an object that contains both the Socket and the
EndPoint that was passed by reference into BeginReceiveFrom, and pull
them both out once you make it to OnDataReceived, you do get a
response, but it is always IPAddress.Any (aka 0.0.0.0.) What is even
the point of passing in the EndPoint by reference into
BeginReceiveFrom if it's always going to come out the same?
More over, there is no way that BeginReceiveFrom will ever alter the
value in "ref EndPoint" because it returns instantly, before any data
has come in. That is the whole point.
So, one solution is to have the client sends it's IP address in every
single packet. But this seems silly - there has to be a way to detect
the IP address that data came in on. No?
Any help would be appreciated. Excuse my code snipits, I typed them
all here, so there may be typos.
Jason
running into what appears to be a common problem but I have not found
a good answer yet.
If this was TCP, when the routine EndReceiveData() is called back
(after making a connection and receiving data) you can access the IP
of the remote host by
EndPoint ep = sock.RemoteEndPoint;
Where this would be useful is UDP, where you don't have a connection
established and you actually need to know the IP address where to send
data.
So, in a UDP synchronous setup, you can write code like this
Receive()
{
IpEndPoint ipep = new IpEndPoint(IPAddress.Any,10000);
EndPoint ep = (EndPoint)ipep;
//When this returns, ipep, will now contain the value of the
RemoteEndPoint.
sock.ReceiveFrom(buffer, ref ep);
//Now you can send data back to that computer
sock.SendTo(buffer, ep);
}
So far so good. You can detect who sent the packet and you can reply
back to them. Easy enough.
But once you move to asynchronous, this doesn't work anymore
BeginReceive()
{
IpEndPoint ipep = new IpEndPoint(IPAddress.Any,10000);
EndPoint ep = (EndPoint)ipep;
//When this returns, ipep, will now contain the value of the
RemoteEndPoint, right?
sock.BeginReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref ep, new
AsyncCallback(OnDataReceived), sock);
}
OnDataReceived(IAsyncResult asyn)
{
Socket sock = (Socket)asyn.AsyncState;
int iRx = sock.EndReceive(asyn);
.... ... ...
}
In this case, you can look at sock.RemoteEndPoint but it will throw an
exception. The argument I hear for this is that this is
connectionless and you don't ever get this, but in the syncronous
example above you DO get this with UDP.
If you pass in an object that contains both the Socket and the
EndPoint that was passed by reference into BeginReceiveFrom, and pull
them both out once you make it to OnDataReceived, you do get a
response, but it is always IPAddress.Any (aka 0.0.0.0.) What is even
the point of passing in the EndPoint by reference into
BeginReceiveFrom if it's always going to come out the same?
More over, there is no way that BeginReceiveFrom will ever alter the
value in "ref EndPoint" because it returns instantly, before any data
has come in. That is the whole point.
So, one solution is to have the client sends it's IP address in every
single packet. But this seems silly - there has to be a way to detect
the IP address that data came in on. No?
Any help would be appreciated. Excuse my code snipits, I typed them
all here, so there may be typos.
Jason