I'm having trouble closing a tcpClient
connection when calling Application.exit()
from a windows form. The problem I'm having is when the form closes the application is still running due to TCP connected devices and I want to close these TCP connections that the app has. I'm using threads per advice on here and I'm successfully connecting devices. When I call server.Stop()
I get the following error:
System.Net.Sockets.SocketException (0x80004005): A blocking operation was interrupted by a call to WSACancelBlockingCall
I've found that the error is linked to this line of code TcpClient client = server.AcceptTcpClient();
which I think keeps connections open when I use threads per each TCP connection.
I've tried using server.Shutdown()
and also using tokens (the program class has one that calls StartServer()
on launch but is blocked by the same error as the TCPService, it's code added below.
Also, If I close the connection from a connected device the application does close.
The full TCP class code is below:
public class TCPService
{
private const int port = 8045;
private bool running;
private static TcpListener server = null;
private Thread t = null;
public ammendDeviceCountDelegate handleDeviceCount;
public void StartServer()
{
string hostName = Dns.GetHostName();
IPAddress myIP = GetIPAddress(hostName);
IPEndPoint localEndPoint = new IPEndPoint(myIP, port);
server = new TcpListener(myIP, port);
server.Start();
running = true;
StartListener();
}
public void stopServer()
{
running = false;
server.Stop();
}
private void StartListener()
{
try
{
while (running)
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
t = new Thread(new ParameterizedThreadStart(HandleDevice));
t.Start(client);
}
}
catch (SocketException e)
{
Console.WriteLine("Exception: {0}", e);
}
}
private void HandleDevice(Object obj)
{
TcpClient client = (TcpClient)obj;
var stream = client.GetStream();
string imei = String.Empty;
string data = null;
Byte[] bytes = new Byte[256];
int i;
handleDeviceCount(false);
try
{
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
string hex = BitConverter.ToString(bytes);
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("{1}: Received: {0}", data, Thread.CurrentThread.ManagedThreadId);
string str = "handshaky";
Byte[] reply = System.Text.Encoding.ASCII.GetBytes(str);
stream.Write(reply, 0, reply.Length);
Console.WriteLine("{1}: Sent: {0}", str, Thread.CurrentThread.ManagedThreadId);
}
client.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.ToString());
client.Close();
}
}
private static IPAddress GetIPAddress(string hostname)
{
IPHostEntry host;
host = Dns.GetHostEntry(hostname);
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip;
}
}
return IPAddress.None;
}
}
Program start method:
private static void startTCPServer()
{
tokenSource = new CancellationTokenSource();
Task.Run(() =>
{
while (running)
{
if (!tokenSource.Token.IsCancellationRequested)
{
tcp.StartServer();
break;
}
}
}, tokenSource.Token);
}