Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

TCP client looses connection. How to debug?

Posted on 2005-04-13
28
Medium Priority
?
394 Views
Last Modified: 2012-06-21
I connect to a TCP Listener through
    tcpClient.Connect(ClientForm.IPAddress, ClientForm.PortNumber)

and then do this on every iteration of a loop

While True
    Dim networkStream As NetworkStream = tcpClient.GetStream()

I then do:
    If networkStream.DataAvailable() Then
    --do something and write back to listener
    End If

    Thread.CurrentThread.Sleep(500)
End While

The listender will periodically send information to this client.  Probably every 10 - 30 minutes at most.  After a while, the above conditional is never ran.  Meaning, the code inside the IF isn't executed.  This only happens on one particular machine.  I've tried it on three machines.  All are behind firewalls and routers.  I can't figure out why the one machine seems to just die on the connection.  Another client on a different machine still gets info from the listener so I know the listener is still active.  I have the client open in VS.NET debugger and see the while loop is still going so the app itself hasn't died.  

How do I make sure the client is still connected?  Also, in general, how can I debug this to figure out the problem?

Thanks,
Brett
0
Comment
Question by:brettr
  • 14
  • 14
28 Comments
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13775669
I can't be too sure but maybe

tcpClient.Client.Connected     will tell you whether the underlying connection is connected

as for debugging it...

    tcpClient.Connect(ClientForm.IPAddress, ClientForm.PortNumber)
    Dim networkStream As NetworkStream = tcpClient.GetStream()
and then do this on every iteration of a loop

While True
    Try
        if Not tcpClient.Client.Connected Then Exit While

        If networkStream.DataAvailable() Then
        --do something and write back to listener
        End If

        Thread.CurrentThread.Sleep(500)

    Catch ex as exception
          Msgbox ex.Message
          Exit While
    End Try
End While

==============

sorry if that wasn't what you were after... also, you can set the timeout for the TcpClient... not sure if that's any help at all.  This is a new area to me so you'll probably make more sense of my own gibberish than me
0
 

Author Comment

by:brettr
ID: 13775974
This is all pretty interesting.

Will the GetStream() be able to pick up anything immeidately after the connect()?

Also, won't I need to make sure I'm connected before attempted the GetStream()

Why do a GetStream right after the connect()?  I do a GetStream as the frist thing on each iteration.  That loop executes right after the connect().

Also, there isn't such a property: tcpClient.Client.Connected.   tcpClient has no Client part.  How else can I tell if there is a connection?

Thanks,
Brett
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13776078
sorry, i pulled that client property straight from the help file and it's a protected  property.

I'll reread your question, my eyes are getting heavy right now :P
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 12

Expert Comment

by:S-Twilley
ID: 13776286
       Dim TcpClient As TcpClient
        Dim myIP As String, myPort As Integer
        TcpClient.Connect(myIP, myPort)

        Dim networkStream As NetworkStream = TcpClient.GetStream()

        While True
           Try
                If networkStream.CanRead Then
                    If networkStream.DataAvailable() Then
                        Dim byRead(TcpClient.ReceiveBufferSize) As Byte
                        networkStream.Read(byRead, 0, CInt(TcpClient.ReceiveBufferSize))
                        Dim returndata As String = System.Text.Encoding.ASCII.GetString(byRead)
                        'Read data
                    End If
                Else
                     'somethings gone wrong
                      Exit While
                End If

                If networkStream.CanWrite Then
                    Dim sendBytes(0) As Byte
                    sendBytes(0) = 0
                    networkStream.Write(sendBytes, 0, sendBytes.Length)
   
                    'Send data... maybe some sort of short message to keep connection alive... incase it closes on idle communication
                Else
                     'somethings gone wrong
                      Exit While
                End If

                Threading.Thread.CurrentThread.Sleep(500)
           Catch Ex As Exception
                Msgbox Ex.Message
           end Try
        End While

==================

I've replaced some variables to make it easie for me to code, but you can change them back....   I figured the connection might get shutdown or something, i dont really know to be honest.  If you keep having probs, maybe you should close the connection and reopen it every so often, sorry,  this is all new to me so im just stabbing in the dark
0
 

Author Comment

by:brettr
ID: 13776342
Thanks.  I'll compile this and try it on the problem machine.  Might be tomorrow morning before I get back to you with results.
0
 

Author Comment

by:brettr
ID: 13781368
On the problem machine, the program does enter this conditional:
   If networkStream.CanWrite And networkStream.CanRead Then


but after a few minutes, it doesn't enter this one:

If networkStream.DataAvailable() Then

I have the same program on another machine and the above conditional is executed.  I will have the problem client continually write back to the listener.  Maybe I will see something that will give a clue.  Any other suggestions you might have are welcome.

Thanks,
Brett
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13781383
what are the actual differences between the two machines? any firewall differences.. different OS.. anything that might give a hint as to why they are giving different output
0
 

Author Comment

by:brettr
ID: 13781506
The problem machine is behind a firewall and router.  The other (server) is a dedicated box on the public Internet.  Not sure if it has a router or not.  However, the app works fine on my home machine behind a router and ZoneAlarm firewall.

If it were really a router/firewall issue, it shouldn't work at all right?  However, it works for a few minutes then dies. Might be 5 or 30 minutes. It varies.  Not sure how a router/firewall could cause that.

I did add a GetStream() here:

 If networkStream.CanWrite And networkStream.CanRead Then
        networkStream = tcpClient.GetStream()

but that didn't help.  This last time it stopped in about five minutes.  The loop still runs but networkStream.DataAvailable() is false.  Ahhgg!
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13781577
Well it might still run... im just wondering if there might be some setting in the firewall or somethin somewhere which either closes the connection due to inactivity... what might be worth investigating is the longest gap between incoming signals that the problem machine can record... if it seems to tend towards the same number, then that might suggest some sort of incoming idle time out:

Add a label called lblMaxGap to your form

Just after your TCPClient declaration:

Dim TcpClient As TcpClient
Dim maxGapS as Integer = 0
Dim tsGap as timespan
Dim dtStart as Datetime = Now

==============================

                   If networkStream.DataAvailable() Then
                        tsGap = Now.Subtract(dtStart)
                        If tsGap.TotalSeconds > maxGapS Then
                              maxGapS = tsGap.TotalSeconds
                              lblMaxGap.Text = maxGapS.ToString
                       End If

                        Dim byRead(TcpClient.ReceiveBufferSize) As Byte
                        networkStream.Read(byRead, 0, CInt(TcpClient.ReceiveBufferSize))
                        Dim returndata As String = System.Text.Encoding.ASCII.GetString(byRead)
                        'Read data

                       dtStart = Now
                    End If
0
 

Author Comment

by:brettr
ID: 13781610
Ok, I'm constantly writing back to the listener now.  In this line:

networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))

Dim returndata As String = Encoding.ASCII.GetString(bytes)

bytes is 8193.  However, returndata is "".  Why is that?  Does the fact that byes has has a length of 8193 mean returndata should also have a value?
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13781639
Add a watch on bytes and see the values to make sure they're not all null or 0
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13781660
sorry... if you've declared bytes with a length  e.g.

Dim byArray(500) as Byte

then it's going to have a length, but might not necessarily be filled with character data once you read from a stream
you'll soon find out when you check the internal values
0
 

Author Comment

by:brettr
ID: 13781859


When I get to the last line here:

tsGap = Now.Subtract(dtStart)
                    If tsGap.TotalSeconds > maxGapS Then
                        maxGapS = tsGap.TotalSeconds
                    End If

                    Dim byRead(tcpClient.ReceiveBufferSize) As Byte
                    networkStream.Read(byRead, 0, CInt(tcpClient.ReceiveBufferSize))

The debugger just stops.  The While loop is no longer executing.  No errors and the app seems ok.  Just no activity.

byRead does have a length but all the values in its array are 0.
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13781884
when you say the debugger stops... is it throwing an exception?  if so, what message?
0
 

Author Comment

by:brettr
ID: 13782373
No exception.  I hit that particular line (it's highlighted yellow) and press F11 again to move forward.  The yellow goes away and I can't move forward in the debugger anymore.  I have a breakpoint on the While statement but it is never hit.  I don't know where the debugger goes off to but I can't walk through anymore.
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13782405
can you post up the code you're using at the mo, just to see if you've missed out a line or something
0
 

Author Comment

by:brettr
ID: 13782517
ConnectInit() runs first then ConnectIt().


Public Class SendReceiveClient

    Public Shared ClientForm As Form1
    Public Shared tcpClient As New System.Net.Sockets.TcpClient
    Public Shared maxGapS As Integer = 0

    Public Shared Sub ConnectIt()
        Dim ConnectAttempts As Integer = 0
        Dim t As Thread
        'Dim IPaddress As String
        Dim Packet As String
        Dim InitialIDSent As Boolean = False

        Dim tsGap As TimeSpan
        Dim dtStart As DateTime = Now

        'IPaddress = "127.0.0.1"
        'IPaddress = "64.106.155.120"

        ConnectInit()
        'write to log file
        'ClientForm.utility.WriteToFile(ClientForm.CurrentDirectory.GetCurrentDirectory, ClientForm.LogFileExec, ClientForm.utility.CurrentDateTime(0) & " - After ConnectInit(): " & ClientForm.Packet)

        Dim networkStream As NetworkStream = tcpClient.GetStream()

        While True
            Try

                If networkStream.CanWrite And networkStream.CanRead Then

                    networkStream = tcpClient.GetStream()

                    '-------------------------------------
                    tsGap = Now.Subtract(dtStart)
                    If tsGap.TotalSeconds > maxGapS Then
                        maxGapS = tsGap.TotalSeconds
                    End If

                    Dim byRead(tcpClient.ReceiveBufferSize) As Byte
                    networkStream.Read(byRead, 0, CInt(tcpClient.ReceiveBufferSize))
                    Dim returndata As String = System.Text.Encoding.ASCII.GetString(byRead)
                    'Read data
                    dtStart = Now
                    '------------------------------------



                    If InitialIDSent Then
                        Packet = "Nothing to Write from: " & Thread.CurrentThread.Name
                    Else
                        Packet = "Connected: " & ClientForm.Packet
                        InitialIDSent = True
                        'write to log file
                        ClientForm.utility.WriteToFile(ClientForm.CurrentDirectory.GetCurrentDirectory, ClientForm.LogFileExec, ClientForm.utility.CurrentDateTime(0) & " - Connected: " & ClientForm.Packet)
                    End If

                    ' Do a simple write.
                    Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(Packet.TrimEnd)
                    networkStream.Write(sendBytes, 0, sendBytes.Length)
                    ' Read the NetworkStream into a byte buffer.
                    Dim bytes(tcpClient.ReceiveBufferSize) As Byte

                    If networkStream.DataAvailable() Then
                        'write to log file
                        ClientForm.utility.WriteToFile(ClientForm.CurrentDirectory.GetCurrentDirectory, ClientForm.LogFileExec, ClientForm.utility.CurrentDateTime(0) & " - networkStream.DataAvailable()=" & networkStream.DataAvailable())


                        'networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
                        ' Output the data received from the host to the console.
                        'Dim returndata As String = Encoding.ASCII.GetString(bytes)

                        If Len(returndata) And (returndata <> ClientForm.ReturnData) Then
                            'write to log file
                            ClientForm.utility.WriteToFile(ClientForm.CurrentDirectory.GetCurrentDirectory, ClientForm.LogFileExec, ClientForm.utility.CurrentDateTime(0) & " - If networkStream.DataAvailable() Then: (next part is)" & vbCrLf & "If Len(returndata) Or (returndata <> ClientForm.ReturnData) Then" & returndata)

                            Console.WriteLine((returndata))
                            ClientForm.ReturnData = returndata
                            returndata = ""

                        Else
                        End If
                    End If

                    ' Output the data received from the host to the console.
                    'Dim returndata As String = Encoding.ASCII.GetString(bytes)
                    'ClientForm.ReturnData = returndata
                    'Console.WriteLine(("Host returned: " + returndata))
                    'returndata = ""

                    'Else
                    '    If Not networkStream.CanRead Then
                    '        Console.WriteLine("cannot not write data to this stream")
                    '        tcpClient.Close()
                    '    Else
                    '        If Not networkStream.CanWrite Then
                    '            Console.WriteLine("cannot read data from this stream")
                    '            tcpClient.Close()
                    '        End If
                    '    End If
                    'End If

                    ' pause so user can view the console output
                    'Console.ReadLine()
                End If

Catch ex As Exception

                If ex.Message = "Operation not allowed on non-connected sockets." Then
                    ConnectInit()
                    ConnectAttempts = +1

                    If ConnectAttempts > 5 Then
                        Exit Sub
                    End If
                Else
                End If

                'write to log file
                ClientForm.utility.WriteToFile(ClientForm.CurrentDirectory.GetCurrentDirectory, ClientForm.LogFileError, ClientForm.utility.CurrentDateTime(0) & " - ERROR (Exiting loop) [ConnectIt] " & ex.Message & vbCrLf & "connectAttempts = " & ConnectAttempts)
                ClientForm.ReturnData = ex.Message
                Exit While
            End Try

            Thread.CurrentThread.Sleep(500)
        End While

        ClientForm.ReturnData = ClientForm.ipE.HostName.ToString
        tcpClient.Close()

    End Sub

    Public Shared Sub ConnectInit()
        tcpClient.SendTimeout = 5000
        Try
            tcpClient.Connect(ClientForm.IPAddress, ClientForm.PortNumber)

            'write to log file
            ClientForm.utility.WriteToFile(ClientForm.CurrentDirectory.GetCurrentDirectory, ClientForm.LogFileExec, ClientForm.utility.CurrentDateTime(0) & " - [ConnectInit] tcpClient.Connect(ClientForm.IPAddress, ClientForm.PortNumber) = " & ClientForm.IPAddress & "/" & ClientForm.PortNumber)

        Catch ex As Exception
            ClientForm.ReturnData = "Time out waiting for response from server.  Please make sure server is listening."
            Thread.CurrentThread.Sleep(5000)

            'write to log file
            ClientForm.utility.WriteToFile(ClientForm.CurrentDirectory.GetCurrentDirectory, ClientForm.LogFileError, ClientForm.utility.CurrentDateTime(0) & " - ERROR [ConnectInit] " & ex.Message)
            ClientForm.ReturnData = ex.Message
        End Try
    End Sub
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13782595
I can't see a prob... if the timing has caused problems... than just take it out, and try and work out yourself if there seems to be a pattern
0
 

Author Comment

by:brettr
ID: 13782764
When you say timing, do you mean the .sleep method?
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13782786
no, i mean the timing between success reads ... i.e. the DateTime stuff we added
0
 

Author Comment

by:brettr
ID: 13782848
oh, ok.  Any other suggestions?
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13782868
Not at the moment :P   ...   im falling asleep at the moment, probably doesnt help
0
 

Author Comment

by:brettr
ID: 13782971
ok, well thanks.

By the way, what does byRead do?

Dim byRead(tcpClient.ReceiveBufferSize) As Byte

Can't find any references to it.  You posted that code.
0
 
LVL 12

Expert Comment

by:S-Twilley
ID: 13783125
byRead is just a variable

made up the name because it was of type Byte

and used for reading :P
0
 

Author Comment

by:brettr
ID: 13785253
On the last line here:
Dim byRead(tcpClient.ReceiveBufferSize) As Byte
                    networkStream.Read(byRead, 0, CInt(tcpClient.ReceiveBufferSize))
                    Dim returndata As String = System.Text.Encoding.ASCII.GetString(byRead)

returndata may get a length of 8193 but if you check the value of returndata, it is "".  This changes my flow somewhat because a little lower in the code, I check for Len(returndata).  I'm looking for the empty string. However, the conditional is met because the length is 8193, although the string value is the empty string.  How do I get around this?

Also for byRead, it has th 8193 length and I see the first 20 or so elements in its array have non zero entries.  Why would it procude an empty string if those entries have values?
0
 
LVL 12

Accepted Solution

by:
S-Twilley earned 375 total points
ID: 13787260
If returnData is just full of spaces or null chars.... ie. its padded, you could use trim on it, and then check it's length...

Dim returndata As String = System.Text.Encoding.ASCII.GetString(byRead)
Dim testReturnData As string = Trim(returnData)

then use testReturnData to test it's length, but use ReturnData for your application if the condition is met.

If the first few entries are non-zero and it's compiling an empty string, my only guess is that you need to use a different encoding format... maybe try something like (guessing here):

Dim returndata As String = System.Text.Encoding.UTF8.GetString(byRead)

or

Dim returndata As String = System.Text.Encoding.UTF7.GetString(byRead)
0
 

Author Comment

by:brettr
ID: 13787277
Ok.  I sitll have that problem with the debugger stopping at this line:

                    networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))

Focus then returns to the main form.  I have commented out the timing code.  No errors and the loop stops processing.  The app is response to user events.  Any ideas why this is happening?
0
 

Author Comment

by:brettr
ID: 13787284
I've also tried it this way:
                    networkStream.Read(bytes, 0, tcpClient.ReceiveBufferSize)

but it does the same thing at that point.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question