As @nobugz has pointed out, you have two problems.
First, you're swallowing any exceptions that occur in DoWork()
. You're catching them, yes, but you're not reporting them. Why does it stop after a few hours? Well, the server might have closed, which would terminate your socket connection. You're not attempting to reconnect, so the thread exits, but the process continues to run. Put some exception reporting in to see why the socket is closing and then handle it accordingly.
And this leads to the second point, namely you have no recovery capability. Once an exception occurs or the socket is gracefully closed for some reason, your thread exits. If you want this to work continually, then you'll need to add logic that attempts to reconnect in the cases where something goes wrong. In other words, the only reason that DoWork()
exits is due to a shutdown event. Otherwise, it will need to loop, attempting to reconnect when errors occur. As @nobugz said, this will also require you to reset the ManualResetEvent
so that your receive loop will work as expected when a reconnect occurs. However, you do not need to call Reset()
in the OnStart()
callback because you've initialized _shutdownEvent
to false
, which is what Reset()
does.
HTH.
EDIT:
This is off the cuff, so I won't verify its accuracy. I'll fix any problem you (or others) may find.
Define a ManualResetEvent
object for shutdown notification. Change the OnStart()
callback to this:
using System.Threading;
ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
Thread _thread;
protected override void OnStart(string[] args)
{
// Create the thread and start it.
_thread = new Thread(DoWork);
_thread.Start();
}
Since you're wanting a TCP connection, I would strongly recommend using TcpClient
as opposed to Socket
. Change your DoWork()
callback to something like this:
using System.Net.Sockets;
private void DoWork()
{
while (!_shutdownEvent.WaitOne(0))
{
TcpClient client = new TcpClient();
try
{
// This is a blocking call. You might want to consider one of the
// asynchronous methods...
client.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8181));
}
catch (Exception ex)
{
// Log the error here.
client.Close();
continue;
}
try
{
using (NetworkStream stream = client.GetStream())
{
byte[] notify = Encoding.ASCII.GetBytes("Client here");
stream.Write(notify, 0, notify.Length);
byte[] data = new byte[1024];
while (!_shutdownEvent.WaitOne(0))
{
int numBytesRead = stream.Read(data, 0, data.Length);
if (numBytesRead > 0)
{
string msg = Encoding.ASCII.GetString(data, 0, numBytesRead);
}
}
}
}
catch (Exception ex)
{
// Log the error here.
client.Close();
}
}
}
Finally, in the OnStop() callback, trigger the thread to shutdown:
protected override void OnStop()
{
_shutdownEvent.Set(); // trigger the thread to stop
_thread.Join(); // wait for thread to stop
}
Now, it is very important to understand that TCP communication is stream-based. What this means is that you are not guaranteed to receive a complete message each time you do a read of the socket (e.g., TcpClient
). If the server sends back the message "Client notification received", reading the socket initially might only get "Client noti". A subsequent read might get "fication recei". A third read might get "ved". It's up to you to buffer the reads together and then process the message. Most protocols will use some kind of header that indicates the type and length of the message. If you're simply using strings, the type of message won't matter since everything's a string. Further, knowing where the string ends could be done using a null terminator instead of prepending the length for example. Just know that reading a TCP socket may only get a portion of the message you're expecting to receive.