Question

I have a windows service which is monitoring a Socket using TCP/IP protocol.As per my requirement my code is establishing a connection to the Machine and receiving data from there and this i want continuously,that's why i have made it in windows service.But the problem that i am facing is that, the service is reading socket ports for 3-4 hours after that automatically stops reading from the port whereas my service status from Services.msc shows its running.

Here is my code for windows Service..

    string ipaddress, textfileSaveLocation;
    Byte[] bBuf;
    string buf;
    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    private System.Threading.Thread _thread;
    private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);

    string df = "";

    public Service1()
    {
        InitializeComponent();
    }

    public void OnDebug()
    {
        OnStart(null);
    }
    protected override void OnStart(string[] args)
    {
        _thread = new Thread(DoWork);
        _thread.Start();

    }
    private void DoWork()
    {
        // create and monitor socket here...

        ipaddress = "192.168.1.100";
        int port = int.Parse("8181");

        byte[] data = new byte[1024];
        string stringData;
        string input;

        IPAddress ipadd = IPAddress.Parse(ipaddress);
        IPEndPoint ipend = new IPEndPoint(ipadd, port);

        sock.NoDelay = false;
        try
        {            
            sock.Connect(ipend);
        }
        catch (Exception dfg)
       {

            return;
        }
        try
        {
            input = "Client here";
            sock.Send(Encoding.ASCII.GetBytes(input));

            while (!_shutdownEvent.WaitOne(0))
            {                  
                data = new byte[1024];
                int recv = sock.Receive(data);
                stringData = Encoding.ASCII.GetString(data, 0, recv);

            }

        }
        catch (Exception DFGFD)
        {
        }

    }

    protected override void OnStop()
    {
        sock.Shutdown(SocketShutdown.Both);
        sock.Close();

        _shutdownEvent.Set();
        _thread.Join();  // wait for thread to stop
    }
}
}

Why is my service stopping receiving data after 3-4 hours ?Please help me to resolve this.

Here is my code to insert ServerMachine data into text file..

                        try
                        {
                            FileStream fs = new FileStream(textfileSaveLocation, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
                            StreamWriter swr = new StreamWriter(textfileSaveLocation,true);
                            swr.WriteLine(stringData);
                            swr.Close();
                            swr.Dispose();
                            fs.Close();
                            fs.Dispose();
                        }
                        catch (Exception Ex)
                        {

                        }
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top