SocketException with Unity C# UDP Receive - c#

I'm using Unity and I'm trying to listen to UDP packets coming in on a specific port. In Unity I have an object with a script attached and the script is designed to simply listen and record data coming in off of the UDP packets. In the script I have my Start function:
public void Start() {
// Setup listener.
this.mListener = new IPEndPoint(IPAddress.Loopback, 0);
// Setup background UDP listener thread.
this.mReceiveThread = new Thread(new ThreadStart(ReceiveData));
this.mReceiveThread.IsBackground = true;
this.mReceiveThread.Start();
}
The function setups the IPEndPoint and the receive thread, then starts the receive thread which is defined as:
private void ReceiveData() {
try {
// Setup UDP client.
this.mClient = new UdpClient(30020);
this.mClient.Client.ReceiveTimeout = 250;
// While thread is still alive.
while(Thread.CurrentThread.IsAlive) {
try {
// Grab the data.
byte[] data = this.mClient.Receive(ref this.mListener);
// Convert the data.
/* REDACTED */
// Separate out the data.
/* REDACTED */
// Store data in the DataSource.
/* REDACTED */
} catch(SocketException e) {
Debug.Log(e.ToString());
continue;
}
}
} catch(Exception e) {
Debug.Log(e.ToString());
}
}
However, when I try to run this I keep getting the following SocketException:
System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
This code was working for months, and I've never seen this exception before. It doesn't really make sense to me. I've tried changing the port but it doesn't seem to have any effect. I'm not exactly sure what happened, or what changes I made that made it behave this way. I have not updated Unity since I started this project. Could my other program not be sending any UDP packets out? Could a lack of UDP packets be the cause of this? The frequency that this SocketException appears in my log is related to the ReceiveTimeout property...

Related

UdpClient beginreceive how to detect when server is off

I have an application that is reading data from a Udp server on 32 different ports that I need to process. I'm using the UdpClient.BeginReceive that is calling itself because I want to listen all the time :
private void ProcessEndpointData(IAsyncResult result)
{
UdpClient client = result.AsyncState as UdpClient;
// points towards whoever had sent the message:
IPEndPoint source = new IPEndPoint(0, 0);
// schedule the next receive operation once reading is done:
client.BeginReceive(new AsyncCallback(this.ProcessEndpointData), client);
// get the actual message and fill out the source:
this.DecodeDatagram(new DatagrammeAscb()
{
Datagramme = this.ByteArrayToStructure<Datagram>(client.EndReceive(result, ref source))
});
}
When I stop the server side, the function is waiting for data (that is normal behavior). What I would like to do is to detect when the server is disconnected and then close all my clients.
I'm asking myself if I should use sockets class to have more controls or just maybe I'm missing something here.
Anyway thanks for your help.

Determine broken connection in TCP server

I wrote a tcp server, each time a client connection accepted, the socket instance returned by Accept or EndAccept which is called handler and many other information gathered in object called TcpClientConnection, I need to determine whether a connection is connected or not at some specific interval times, the Socket.Connected property is not reliable and according to the documentation i should use the Poll method with SelectRead option to do it.
with a test scenario i unplug the client cable, and wait for broken alarm which is built upon the handler.Poll(1, SelectMode.SelectRead), it should return true but never it happened.
This is a fundamentally caused by the way the TCP and IP protocols work. The only way to detect if a connection is disconnected is to send some data over the connection. The underlying TCP protocol will cause acknowledgements to be sent from the receiver back to the sender thereby allowing a broken connection to be detected.
These articles provide some more information
Do I need to heartbeat to keep a TCP connection open?
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
According to the documentation of Socket.Poll:
This method cannot detect certain kinds of connection problems, such as a broken network cable, or that the remote host was shut down ungracefully. You must attempt to send or receive data to detect these kinds of errors.
In another words - Poll is useful for checking if some data arrived and are available to your local OS networking stack.
If you'd need to detect the connection issues you need to call blocking read (e.g. Socket.Receive)
You can also build a simple initialization miniprotocol to exchange some agreed 'hello' back and forth message.
Here is a simplified example how you can do it:
private bool VerifyConnection(Socket socket)
{
byte[] b = new byte[1];
try
{
if (socket.Receive(b, 0, 1, SocketFlags.None) == 0)
throw new SocketException(System.Convert.ToInt32(SocketError.ConnectionReset));
socket.NoDelay = true;
socket.Send(new byte[1] { SocketHelper.HelloByte });
socket.NoDelay = false;
}
catch (Exception e)
{
this._logger.LogException(LogLevel.Fatal, e, "Attempt to connect (from: [{0}]), but encountered error during reading initialization message", socket.RemoteEndPoint);
socket.TryCloseSocket(this._logger);
return false;
}
if (b[0] != SocketHelper.HelloByte)
{
this._logger.Log(LogLevel.Fatal,
"Attempt to connect (from: [{0}]), but incorrect initialization byte sent: [{1}], Ignoring the attempt",
socket.RemoteEndPoint, b[0]);
socket.TryCloseSocket(this._logger);
return false;
}
return true;
}

C#: System.Net.Sockets.TcpListener is sometimes not closing Socket properly

in one of my projects I have implemented a small HTTP server to stream the video data of a connected webcam. For this task I'm utilizing the System.Net.Sockets.TcpListener from .NET Framework 4.5, which listens to a pre-configured endpoint and uses the AcceptSocketAsync() mtehod to wait for incomming requests. You can see the relevant code parts below:
this.server = new TcpListener(endpoint);
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, 0));
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.server.Start();
...
this.listenTask = Task.Factory.StartNew(this.Listen);
...
private async void Listen()
{
try
{
while (this.server.Server.IsBound)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Factory.StartNew(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
This works fine, when I start the application and the HTTP server is started for the first time. However, when I stop the HTTP server (done via CheckBox in the settings of the application) the unverlying listening socket is sometimes not closed. When I check for the state of the sockets via console (netstat -ano) I can see that the socket is still in state LISTENING. The resulting problem is, when I restart the HTTP server again I get an System.Net.Sockets.SocketException with the message "Only one usage of each socket address is normally permitted", which is not surprising.
The relevant code part for stopping the HTTP server is as follows:
...
if (this.server != null)
{
if (this.server.Server != null)
{
if (this.server.Server.Connected)
{
this.server.Server.Shutdown(SocketShutdown.Both);
this.server.Server.Disconnect(true);
}
this.server.Server.Close();
}
this.server.Stop();
}
...
I also keep track of my open connections and close them after finishing the transmission of data and when stopping the server. None of the connection sockets stays opened, so I believe only the listening socket should be relevant for this problem.
I already tried various combinations/orders of the Shutdown(), Disconnect(), Close() and Stop() methods when stopping the server, as well as setting/unsetting several options when starting the server like Linger and ReuseAddress, which sometimes seemed to fix the problem at first, but then a few days later the problem occurred again.
I also tried to "force" the listening socket to close when stopping the server using GetTcpTable(...) and SetTcpEntry(...) from iphlpapi.dll, as described in this question: How to close a TCP connection by port?
Unfortunately, this approach did not work for me (it change anything about the state of the listening socket at all).
As I'm a little bit clueless of what else I could do, I'm asking here if somebody has an idea of what might cause the discribed problem or how to solve it. Any help would be greatly appreciated.
Kind regards,
Chris
You should almost always leave TcpListener.Server alone. It's there so you can set socket options on it, not use it for control purposes.
So your Listen should be:
private async void Listen()
{
try
{
while (true)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Run(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
(assuming you do actually want one thread per client, an architecture I do not recommend in general).
When you're ready to stop, just stop:
if (this.server != null)
{
this.server.Stop();
}
If you do not have any special requirement, it is suggested to make use of TcpListener class and its methods only or if you have such requirement, do not use TcpListener and start with the Raw socket.
TcpListener class is self sufficient to provide method like
Start(), AcceptTcpClient() and Stop().
You can create a List<TcpClient> and loop through each client and call client.close() after calling Stop() on the TcpListener instance.
A very good example of client server communication is on MSDN:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.110).aspx
Regards
On server socket, shutdown & disconnect is not needed for listening sockets. Those calls are needed only for connected sockets. Replace the socket stop with below code:
if (this.server != null)
{
if (this.server.Server != null)
{
this.server.Server.Close();
this.server.Server = NULL;
}
}
I would dispose of your socket connections once you have closed them. The documentation says they should be disposed after closed but personally I like to say when to dispose of anything that use the IDisposable interface.

Using C# UDP Client

I'm making a program which needs to be listening for UDP Data at all times.
My current idea is have this method running constantly in one thread listening for packets and then adding them to a list ready to be dealt with in other threads. The main problem is I would also like to add the received IP to a list so that the other thread can deal with it but I don't know if the program stops using the Receive method for a moment if it will lose packets received while processing the data or if it can still grab them from a queue.
public void listen()
{
try
{
packetQueue.Add(receivingUdpClient.Receive(ref RemoteIpEndPoint));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
network traffic should be buffered on your network card so the data should be consistent even if you are listening inconsistently. as for the IP you can get it from the endpoint so you'll need to pass that as well:
public void listen()
{
try
{
packetQueue.Add(receivingUdpClient.Receive(ref RemoteIpEndPoint), RemoteIpEndPoint);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
If you want to miss as little time as possible in between receives I suggest you use BeginReceive and start a new BeginReceive in the callback before processing the received data in the callback. this will add some synchronization complexity though.
I know of no way to get the IP from the Udp packet. You need to get it form the EndPoint:
byte[] receivedBytes = oClientListener.Receive(ref endPoint);
IPAddress = endPoint.Address;
PackQueue.Add( new PacketOfSomeType( receivedBytes, IPAdress ) );
Also, your program will need to run VERY SLOWLY to start losing any packets - windows will buffer those for you, so long as you have your client listener set up!

How can I unbind a socket in C#?

I'm having some problems reusing a server socket in a test application I've made. Basically, I have a program that implements both the client side and the server side. I run two instances of this program for testing purposes, one instance starts to host and the other connects. This is the listening code:
private void Listen_Click(object sender, EventArgs e)
{
try
{
server = new ConnectionWrapper();
HideControls();
alreadyReset = false;
int port = int.Parse(PortHostEdit.Text);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, port);
server.connection.Bind(iep); // bellow explanations refer to this line in particular
server.connection.Listen(1);
server.connection.BeginAccept(new AsyncCallback(OnClientConnected), null);
GameStatus.Text = "Waiting for connections on port " + port.ToString();
}
catch (Exception ex)
{
DispatchError(ex);
}
}
private void OnClientConnected(IAsyncResult iar)
{
try
{
me = Player.XPlayer;
myTurn = true;
server.connection = server.connection.EndAccept(iar); // I will only have one client, so I don't care for the original listening socket.
GameStatus.Text = server.connection.RemoteEndPoint.ToString() + " connected";
StartServerReceive();
}
catch (Exception ex)
{
DispatchError(ex);
}
}
This works fine the first time. However, after a while (when my little game ends), I call Dispose() on the server object, implemented like this:
public void Dispose()
{
connection.Close(); // connection is the actual socket
commandBuff.Clear(); // this is just a StringBuilder
}
I also have this in the object constructor:
public ConnectionWrapper()
{
commandBuff = new StringBuilder();
connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connection.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
I get no error when I click the Listen button a second time. The client side connects just fine, however my server side does not detect the client connection a second time, which basically renders the server useless anyway. I'm guessing it's connecting to the old, lingering socket, but I have no idea why this is happening to be honest. Here's the client connection code:
private void Connect_Click(object sender, EventArgs e)
{
try
{
client = new ConnectionWrapper();
HideControls();
alreadyReset = false;
IPAddress ip = IPAddress.Parse(IPEdit.Text);
int port = int.Parse(PortConnEdit.Text);
IPEndPoint ipe = new IPEndPoint(ip, port);
client.connection.BeginConnect(ipe, new AsyncCallback(OnConnectedToServer), null);
}
catch (Exception ex)
{
DispatchError(ex);
}
}
If I do netstat -a in CMD, I see that the port I use is still bound and its state is LISTENING, even after calling Dispose(). I read that this is normal, and that there's a timeout for that port to be "unbound".
Is there a way I can force that port to unbind or set a very short timeout until it automatically gets unbound? Right now, it only gets unbound when I exit the program. Maybe I'm doing something wrong in my server? If so, what could that be? Why does the client connect fine, yet the server side doesn't detect it a second time?
I could make the socket always listen, not dispose it, and use a separate socket to handle the server connection, which would probably fix it, but I want other programs to be able to use the port between successive play sessions.
I remember seeing another question asking this, but there was no satisfactory answer for my case there.
There may be a couple of reasons why the port would stay open, but I think you should be able to resolve your issue by using an explicit LingerOption on the socket:
LingerOption lo = new LingerOption(false, 0);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
This basically turns the socket shutdown into an abortive shutdown instead of a graceful shutdown. If you want it to be graceful but just not wait as long, then use true in the constructor and specify a small but nonzero value for the timeout.
I just noticed this line, which is almost undoubtedly part of your problem:
server.connection = server.connection.EndAccept(iar); // I will only have one client, so I don't care for the original listening socket.
The comment you've written here is, well, wrong. Your wrapper class really shouldn't allow connection to be written to at all. But you cannot simply replace the listening socket with the client socket - they're two different sockets!
What's going to happen here is that (a) the listening socket goes out of scope and therefore never gets explicitly closed/disposed - this will happen at a random time, possibly at a nasty time. And (b) the socket that you do close is just the client socket, it will not close the listening socket, and so it's no wonder that you're having trouble rebinding another listening socket.
What you're actually witnessing isn't a socket timeout, it's the time it takes for the garbage collector to realize that the listening socket is dead and free/finalize it. To fix this, you need to stop overwriting the listening socket; the Dispose method of your wrapper class should dispose the original listening socket, and the client socket should be tracked separately and disposed whenever you are actually done with it.
In fact, you should really never need to rebind another listening socket at all. The listening socket stays alive the whole time. The actual connection is represented by just the client socket. You should only need to dispose the listening socket when you finally shut down the server.
I agree with the previous answer, you should also "shutdown" to allow any existing activity to complete and then close the socket flagging it for reuse...
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(true);

Categories