CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2

Hybrid View

  1. #1
    Join Date
    Nov 2012
    Posts
    1

    Question Socket idle time problem in Windows Service

    /*
    Hello,

    I wrote class for management clients socket connection using Windows Service.
    In this class I want to manage client idle time. For this I'm using SocketPaketWithTimer,
    with System.Timers.Timer and OnTimerElapsed event. The problem is, that after OnTimerElapsed
    event occurred I want pass parameters in CloseClientSocket, but at this moment windows service stops responding
    (When client sends "Close" the socket service closes client socket without problem).
    This occurs on second client close. I think the problem is Timer event, which is executed in separate thread.

    Here is my class:
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    using System.Collections;
    using TheCodeKing.Net.Messaging;
    using System.Globalization;
    using System.Diagnostics;
    using System.Threading;
    using System.ComponentModel;

    namespace www.gpos.ge_ws
    {
    class clsSocketTest
    {
    private int intGlobalClientCount = 0;
    private string strGlobalConnIdent = "";
    public AsyncCallback pfnWorkerCallBack;

    /// <summary>
    /// An ArrayList is used to keep track of worker sockets that are designed
    /// to communicate with each connected client. Make it a synchronized ArrayList For thread safety
    /// </summary>
    private static System.Collections.ArrayList arrayWorkerSocketList =
    ArrayList.Synchronized(new System.Collections.ArrayList());

    private Socket mainSocket;

    public class SocketPacket
    {
    public Socket m_currentSocket;
    public int m_clientNumber;
    public string m_clientIdent;
    public DateTime m_openDateTime;
    // Buffer to store the data sent by the client
    public byte[] dataBuffer = new byte[1024];

    // Constructor which takes a Socket and a client number
    public SocketPacket(System.Net.Sockets.Socket socket, int clientNumber, string clientIdent, DateTime connOpenDateTime)
    {
    m_currentSocket = socket;
    m_clientNumber = clientNumber;
    m_clientIdent = clientIdent;
    m_openDateTime = connOpenDateTime;
    }
    }

    public class SocketPaketWithTimer
    {
    public SocketPacket m_currentSocketPacket;
    public System.Timers.Timer m_connIdleTimer;

    public SocketPaketWithTimer(SocketPacket objSocketPacket, System.Timers.Timer objSocketPacketTimer)
    {
    m_currentSocketPacket = objSocketPacket;

    if (objSocketPacketTimer == null)
    {
    m_connIdleTimer = new System.Timers.Timer(20000);

    m_connIdleTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerElapsed);
    m_connIdleTimer.AutoReset = false;
    m_connIdleTimer.Enabled = true;
    m_connIdleTimer.Start();
    }
    else
    {
    m_connIdleTimer = objSocketPacketTimer;
    }
    }

    private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
    try
    {
    CloseClientSocket(m_currentSocketPacket, m_connIdleTimer);
    }
    catch (Exception exc)
    {

    }
    }
    }

    /// <summary>
    /// კონსტრუქტორი Socket კლასის
    /// </summary>
    public clsSocketTest(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
    {
    mainSocket = new Socket(addressFamily, socketType, protocolType);
    }

    /// <summary>
    /// TCP Server იწყებს მოსმენას
    /// </summary>
    public void Start(IPAddress ipAddress, int intPort)
    {
    try
    {
    IPEndPoint ipLocal = new IPEndPoint(ipAddress, intPort);
    // აბავს სერვერს ლოკალურ IP მისამართს
    mainSocket.Bind(ipLocal);
    // ხსნის პორტს
    mainSocket.Listen(4);
    // იძახებს call back ფუნქციას კავშირისათვის
    mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
    }
    catch (Exception exc)
    {
    clsSystemEvents.writeEvent("შეცდომა სოკეტის ჩართვის დროს: " + exc.Message, EventLogEntryType.Error, 1);
    }
    }

    /// <summary>
    /// აჩერებს TCP Server და ხურავს ყველა მიერთებულ კავშირს
    /// </summary>
    public void Stop()
    {
    try
    {
    Socket workerSocket = null;
    for (int i = 0; i < arrayWorkerSocketList.Count; i++)
    {
    workerSocket = (Socket)arrayWorkerSocketList[i];
    if (workerSocket != null)
    {
    workerSocket.Close();
    workerSocket = null;
    }
    }
    if (mainSocket != null)
    {
    mainSocket.Close();
    }
    }
    catch (Exception exc)
    {
    clsSystemEvents.writeEvent("შეცდომა სოკეტის გამორთვის დროს: " + exc.Message, EventLogEntryType.Error, 1);
    }
    }

    /// <summary>
    /// მართავს კავშირებს
    /// </summary>
    private void OnClientConnect(IAsyncResult asyn)
    {
    DateTime dtCurrentDateTime = System.DateTime.Now;

    try
    {
    // Here we complete/end the BeginAccept() asynchronous call
    // by calling EndAccept() - which returns the reference to
    // a new Socket object
    Socket workerSocket = mainSocket.EndAccept(asyn);

    // Now increment the client count for this client
    // in a thread safe manner
    Interlocked.Increment(ref intGlobalClientCount);
    strGlobalConnIdent = clsAddings.RandomString();

    SocketPacket socketPacket = new SocketPacket(workerSocket, intGlobalClientCount, strGlobalConnIdent, dtCurrentDateTime);
    SocketPaketWithTimer socketPaketWithTimer = new SocketPaketWithTimer(socketPacket, null);

    // Add the workerSocket reference to arrayWorkerSocketList ArrayList
    arrayWorkerSocketList.Add(socketPaketWithTimer);

    /*
    // Send a welcome message to client
    string msg = "Welcome client " + m_clientCount + "\n";
    SendMsgToClient(msg, m_clientCount);
    // Update the list box showing the list of clients (thread safe call)
    UpdateClientListControl();
    */

    // Let the worker Socket do the further processing for the
    // just connected client
    WaitForData(socketPaketWithTimer);

    // Since the main Socket is now free, it can go back and wait for
    // other clients who are attempting to connect
    mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
    }
    catch (Exception exc)
    {
    clsSystemEvents.writeEvent("შეცდომა კომუნიკაციის დამყარების დროს: " + exc.Message, EventLogEntryType.Error, 1);
    }
    }

    /// <summary>
    /// ელოდება მონაცემებს მიერთებული მომხარებლისგან
    /// </summary>
    private void WaitForData(SocketPaketWithTimer socPacketWithTimer)
    {
    int aa = Thread.CurrentThread.ManagedThreadId;

    try
    {
    if (pfnWorkerCallBack == null)
    {
    // Specify the call back function which is to be
    // invoked when there is any write activity by the
    // connected client
    pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
    }

    SocketPacket theSocPkt = socPacketWithTimer.m_currentSocketPacket;

    theSocPkt.m_currentSocket.BeginReceive(theSocPkt.dataBuffer, 0,
    theSocPkt.dataBuffer.Length,
    SocketFlags.None,
    pfnWorkerCallBack,
    socPacketWithTimer);
    }
    catch (ObjectDisposedException exc)
    {
    System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
    }
    }

    /// <summary>
    /// ახორციელებს მონაცემების მიღებას
    /// </summary>
    /// <param name="asyn"></param>
    private void OnDataReceived(IAsyncResult asyn)
    {
    SocketPaketWithTimer socketData = (SocketPaketWithTimer)asyn.AsyncState;
    DateTime dtCurrentDateTime = System.DateTime.Now;

    try
    {
    // აჩერებს სოკეტის ტაიმერს
    socketData.m_connIdleTimer.Stop();

    // Complete the BeginReceive() asynchronous call by EndReceive() method
    // which will return the number of characters written to the stream
    // by the client
    int iRx = socketData.m_currentSocketPacket.m_currentSocket.EndReceive(asyn);
    char[] chars = new char[iRx + 1];
    // Extract the characters as a buffer
    System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
    int charLen = d.GetChars(socketData.m_currentSocketPacket.dataBuffer,
    0, iRx, chars, 0);

    System.String szData = new System.String(chars);

    // კავშირის დახურვა
    if (szData == "Close\0")
    {
    CloseClientSocket(socketData.m_currentSocketPacket, socketData.m_connIdleTimer);
    return;
    }

    // Continue the waiting for data on the Socket
    WaitForData(socketData);

    socketData.m_connIdleTimer.Start();
    }
    catch (ObjectDisposedException exc)
    {
    System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
    }
    catch (SocketException se)
    {
    if (se.ErrorCode == 10054) // Error code for Connection reset by peer
    {
    string msg = "Client " + socketData.m_currentSocketPacket.m_clientNumber + " Disconnected" + "\n";

    // Remove the reference to the worker socket of the closed client
    // so that this object will get garbage collected
    arrayWorkerSocketList[socketData.m_currentSocketPacket.m_clientNumber - 1] = null;
    //UpdateClientListControl();
    }
    else
    {
    //MessageBox.Show(se.Message);
    }
    }
    }

    /// <summary>
    /// Close worker socket
    /// </summary>
    private static void CloseClientSocket(SocketPacket objSocketPaketToClose, System.Timers.Timer objSocketTimerToClose)
    {
    try
    {
    if (objSocketTimerToClose != null)
    {
    objSocketTimerToClose.Stop();
    objSocketTimerToClose.Dispose();
    objSocketTimerToClose = null;
    }

    if (objSocketPaketToClose.m_currentSocket != null)
    {
    objSocketPaketToClose.m_currentSocket.Shutdown(SocketShutdown.Both);
    objSocketPaketToClose.m_currentSocket.Disconnect(false);
    objSocketPaketToClose.m_currentSocket.Close();
    objSocketPaketToClose.m_currentSocket = null;
    arrayWorkerSocketList[objSocketPaketToClose.m_clientNumber - 1] = null;
    }
    }
    catch (Exception exc)
    {
    clsSystemEvents.writeEvent("შეცდომა კომუნიკაციის დახურვის დროს: " + exc.Message, EventLogEntryType.Error, 1);
    }
    }
    }
    }

  2. #2
    Join Date
    Jul 2012
    Posts
    90

    Re: Socket idle time problem in Windows Service

    You're going to need to be able to step through your code to find the problem. With Windows Services this can be a bit trickier than a normal exe or web project.

    First, you'll need to find the InstallUtil.exe for the .Net Framework version that you are working with. It is installed with your .Net Framework. Mine are under C:\Windows\Microsoft.NET\Framework\ in the folder for the version. Versions 2.0, 3.0, and 3.5 use the one in the folder for 2.0 (mine is v2.0.50727). The one for 4.0 is under the 4.0 folder (mine is v4.0.30319). It is simple to use, see http://msdn.microsoft.com/en-us/libr...(v=vs.90).aspx.

    Next, I ad some code in my OnStart handler for my service to allow time to attach the Visual Studio debugger to the running service e.g.

    Code:
    bool hook = true;
    if (hook)
    {
        System.Threading.Thread.Sleep(15000);
    }
    This will give you about 15 seconds to attach once the service is started. I normally put a stop on the next line.

    1. Install your service's exe (the one in your project's Debug folder) using InstallUtil.exe.

    2. Open the Computer Management Console and start the service.

    3. Immediately switch to Visual Studio and click on "Tools\Attatch to Process" from the menu bar.

    4. Select your running service from the dialog and click the Attach button.

    Once attached to the process and the 15 seconds has elapsed, you will be able to step through your code in debug mode just like any other type of project.

    Put plenty of stops through out the code that you need to check and remember to remove the code you added to your OnStart.
    Last edited by CGKevin; November 6th, 2012 at 06:16 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured