TcpServer acting strangely

Last post 05-09-2008 6:24 AM by ParrotBoy. 2 replies.

Sort Posts:

  • TcpServer acting strangely

    05-09-2008, 5:37 AM
    • Contributor
      2,378 point Contributor
    • ParrotBoy
    • Member since 10-08-2003, 1:56 AM
    • England
    • Posts 484

    Hi everyone, apologies that this is not strictly a webservice question, it seemed like the forum that fit the most.

     I'm building a multi-threaded TcpServer class, which will take XML data over a certain port, process it and return a result. Here is my class (with non-relevant bits removed):

    public class TcpListener
        {
            private readonly System.Net.Sockets.TcpListener _TcpListener;
            private readonly Thread _ListenThread;
    
            public TcpListener(ILogWriter LogWriter)
            {
                this.LogWriter = LogWriter;
                WriteToLog(10, "TcpListener Initialized.");
                _TcpListener = new System.Net.Sockets.TcpListener(IPAddress.Any, 3000);
                _ListenThread = new Thread(ListenForClients);
                _ListenThread.Start();
            }
    
            // Public properties removed for clarity
    
            public void Stop()
            {
                WriteToLog(10, "TcpListener.Stop.");
                _ListenThread.Abort();
                _TcpListener.Stop();
            }
    
            /// <summary>
            ///     Blocks until a client has connected to the server. (Blocking means that the AcceptTcpClient method waits for data to be
            ///     sent before it returns.) Then creates a thread to handle communication with the connected client.
            /// </summary>
            private void ListenForClients()
            {
                WriteToLog(10, "ListenForClients entered.");
                try 
                {
                    _TcpListener.Start();
                }
                catch(Exception e)
                {
                    WriteToLog(5, "ERROR Starting Inner Listener: " + e.Message);
                }
                WriteToLog(10, "Started inner listener");
    
                while(true)
                {
                    WriteToLog(10, "ListenForClients - loop starting.");
                    TcpClient objClient = _TcpListener.AcceptTcpClient();
                    Thread objClientThread = new Thread(HandleClientCommunication);
                    WriteToLog(10, "ListenForClients - about to start HandleClientCommunication thread.");
                    objClientThread.Start(objClient);
                }
            }
    
            private void HandleClientCommunication(object Client)
            {
                WriteToLog(10, "HandleClientCommunication entered.");
    
                WriteToLog(10, "HandleClientCommunication entered a bit more.");
    
                try
                {
                    if (!(Client is TcpClient))
                    {
                        WriteToLog(5, "HandleClientCommunication - Throwing ArgumentException - Client must be a TcpClient object");
                        throw new ArgumentException("Client must be a TcpClient object.");
                    }
                    else
                        WriteToLog(10, "HandleClientCommunication - Client is of type " + Client.GetType() + ", continuting processing");
                }
                catch
                {
                    WriteToLog(5, "HandleClientCommunication - ERROR OCCURED");
                    return;
                }
    
                TcpClient objClient = (TcpClient) Client;
                NetworkStream objClientStream = objClient.GetStream();
    
                byte[] bteMessage = new byte[4096];
    
                while(true)
                {
                    WriteToLog(10, "HandleClientCommunication loop started.");
                    int intBytesRead = 0;
                    string strResponse;
    
                    try
                    {
                        // Blocks until a client sends a message.
                        intBytesRead = objClientStream.Read(bteMessage, 0, 4096);
                        WriteToLog(10, "HandleClientCommunication - found client message with length of " + intBytesRead + ".");
                    }
                    catch
                    {
                        WriteToLog(7, "HandleClientCommunication - socket error.");
                        // A socket error has occured.
                        break;
                    }
    
                    // If 0 then the client has disconnected from the server.
                    if (intBytesRead == 0)
                    {
                        WriteToLog(7, "HandleClientCommunication - 0 bytes read error.");
                        break;
                    }
    
                    // Message has successfully been recieved.
                    ASCIIEncoding objEncoder = new ASCIIEncoding();
                    string strRequestMessage = objEncoder.GetString(bteMessage, 0, intBytesRead);
                    WriteToLog(10, "HandleClientCommunication - recieved string '" + strRequestMessage + "'.");
    
                    // When this point is reached the XML is always processed properly and the test succeeds.
                    // Actual business logic removed for clarity - this bit is definitely working!
    
                    // Send the response back
                    WriteToLog(10, "HandleClientCommunication - returning response - " + strResponse);
                    NetworkStream objReturnStream = objClient.GetStream();
                    byte[] bteResponse = objEncoder.GetBytes(strResponse);
                    objReturnStream.Write(bteResponse, 0, bteResponse.Length);
                    objReturnStream.Flush();
                }
    
                WriteToLog(10, "HandleClientCommunication - closing client.");
                objClient.Close();
            }
        }

     
     I'm testing this with a unit test named SendExampleRequest1, but the results are very unpredictable. My tests are under the NUnit framework, running in resharper's client withing VS2005. Heres the test code:

    string strIP = "127.0.0.1"; // Local address
    OrderProcessingMiddleware.Listeners.TcpListener objListener = null;
    
    Console.WriteLine("*********************\nCONNECTING TO LISTENER ON LOCAL PC\n************************");
    
    // Start the listener
    objListener = new OrderProcessingMiddleware.Listeners.TcpListener(new SqlServerLogWriter());
    
    Console.WriteLine("Creating client");
    TcpClient objClient = new TcpClient();
    IPEndPoint objEndPoint = new IPEndPoint(IPAddress.Parse(strIP), 3000);
    objClient.Connect(objEndPoint);
    NetworkStream stmClient = objClient.GetStream();
    Console.WriteLine("Client connected and stream obtained");
    
    ASCIIEncoding objEncoder = new ASCIIEncoding();
    byte[] bteBuffer = objEncoder.GetBytes(RequestText);
    stmClient.Write(bteBuffer, 0, bteBuffer.Length);
    stmClient.Flush();
    Console.WriteLine("Data written to stream");
    
    byte[] bteResponse = new byte[256];
    int intBytes = stmClient.Read(bteResponse, 0, bteResponse.Length);
    string strResponseData = objEncoder.GetString(bteResponse, 0, intBytes);
    Console.WriteLine("Recieved: '" + strResponseData + "'");
    
    Console.WriteLine("About to abort thread");
    stmClient.Close();
    
    Console.WriteLine("Closing listener");
    objListener.Stop();
    

      All this is doing is checking that we get a response, any response, from the listener. I'm getting very erratic results, here are just the last few, they state the last WriteToLog item which worked (the logs themselves are in an SQL Server table):

    13) SUCCESS! - Response returned - TCP client stopped!
    14) ListenForClients - loop starting.
    15) HandleClientCommunication entered.
    16) ListenForClients - about to start HandleClientCommunication thread
    17) HandleClientCommunication entered.
    18) ListenForClients - loop starting.

    ## Restarted test environment to ensure that the TcpListener was closed

    19) ListenForClients - loop starting.

    ## Added extra console write statements to unit test code for when a client is created, connected, and written to
    ## Restarted test environment to ensure that the TcpListener was closed

    20) SUCCESS! - Response returned - TCP client stopped!
    21) ListenForClients - loop starting.        Last Console comment: Data written to stream
    22) ListenForClients - loop starting.        Last Console comment: Data written to stream
     

    I really don't understand how it can seemingly randomly just stop working. For example - check out test 15 - the last log was "HandleClientCommunication entered", however in the code the next statement which would be executed is simply another log of "HandleClientCommunication entered a bit more", but it just stops instead of moving to the next statement!

     I REALLY REALLY will appreciate any help anybody could give me. I have all the logs if it will help you out at all.
     

    Please mark posts as the answer if I was helpful. Thanks!

    Visit my blog
  • Re: TcpServer acting strangely

    05-09-2008, 6:10 AM
    Answer
    • Star
      9,462 point Star
    • kamii47
    • Member since 05-26-2005, 4:04 PM
    • Karachi, Pakistan
    • Posts 2,198

    IT would be better if you post this in Microsoft Forum [Network section]

    http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=40&SiteID=1 

    Kamran Shahid
    Sr. Software Engineer
    (MCP,MCAD.net,MCSD.net,MCTS,MCPD.net[web])

    Remember to click "Mark as Answer" on the post that helps U
  • Re: TcpServer acting strangely

    05-09-2008, 6:24 AM
    • Contributor
      2,378 point Contributor
    • ParrotBoy
    • Member since 10-08-2003, 1:56 AM
    • England
    • Posts 484

    Great stuff - thanks! 

    Please mark posts as the answer if I was helpful. Thanks!

    Visit my blog
Page 1 of 1 (3 items)