Re: How is this conditional able to execute?



As I said, if you have:

networkStream = tcpClient.GetStream()

inside the loop, then each time the loop iterates then a NEW reference to
the NetworkStream object is being obtained at a rate rate of 2 times every
second.

It is not necessary to do this and, as I also said, I think it is one of the
causes of your problems.

What I am trying to say, without upsetting you, is - having it inside the
loop is plain downright dumb.

The 'If networkStream.DataAvailable Then' has a matching 'End If'. It the
one directly before the 'Catch ...'.
Note that the test of returndata is not a type. It is all on one line.
Because of this it does not have (does not need) an 'End If'. To put it back
in you must have split the line which is not what I intended. The code I
posted was copied and pasted from a project where the code works as shown.

We keep coming back to the question, how do you know that returndata is
equal to "" when the code hits the test? What mechanism are you using to
tell you this? We've been asking that from the start but you have never told
us.

If, as you think, returndata = "" when the test is hit then the test will
evaluate to False and the conditional code will NOT be executed.

Put this in a new project an try it:

Dim returndata As String = ""
Dim ClientForm_ReturnData As String = "xyz"
Console.WriteLine("returndata = *{0}*", returndata)
If returndata <> "" AndAlso returndata <> ClientForm_ReturnData Then
Console.WriteLine("Changing")
ClientForm_ReturnData = returndata
End If
Console.WriteLine("ClientForm_ReturnData = {0}", ClientForm_ReturnData)

The result should be:

returndata = **
ClientForm_ReturnData = xyz

Now change Dim returndata As String = "" to Dim returndata As String = "abc"
and run it again.

The result should be:

returndata = *abc*
Changing
ClientForm_ReturnData = abc
abc
Now change Dim returndata As String = "" to Dim returndata As String = "xyz"
and run it again.

The result should be:

returndata = *xyz*
ClientForm_ReturnData = abc

Not that 'Changing' is only displayed when returndata is NOT an empty string
and returndata is NOT equal to ClientForm_ReturnData.

If you are sure that the conditional code is being executed when (you think)
returndata = "" then returndata does not contain what you think it does. To
see what is actually in it, go back to dumping out the values of the
individual bytes.

Try this:

Dim _b() As Byte = New Byte() {0, 0, 0}
Dim _s As String = System.Text.Encoding.UTF8.GetString(_b)
Console.WriteLine("_s.Length = {0}", _s.Length)
Console.WriteLine("_s = *{0}*", _s)

Note that the length of the string is 3 but that nothing shows after the
first *.

Change Dim _b() As Byte = New Byte() {0, 0, 0} to Dim _b() As Byte = New
Byte() {54, 0, 0}

Run it again and note that while the length of the string is still 3, the
string shows as "6". Also note that the trailing * is not shown.

Change Dim _b() As Byte = New Byte() {54, 0, 0} to Dim _b() As Byte = New
Byte() {54, 54, 54}


Run it again and note that the length of the string is still 3, the string
shows as "666" and both *'s show.

What you are seeing is the effect of Null or Chr(0) characters in the
string, and you need to learn how to handle them.

Change Dim _b() As Byte = New Byte() {54, 54, 54} to Dim _b() As Byte = New
Byte() {54, 0, 0}

Change Dim _s As String = System.Text.Encoding.UTF8.GetString(_b) to Dim _s
As String = System.Text.Encoding.UTF8.GetString(_b).Trim(Char.MinValue)

Run it again and note that the length of the string is now 1, the string
shows as "6" and both *'s show.

This is the result of trimming leading/trailing Null characters from the
string.

In addition, what value do you get for bytesread after the
networkStream.Read? It is possible, but I would be surprised if it is
actually 8192.

The next question is, what is the server end of the connection actually
supposed to be sending?

Don't go to bed so early tonight, it's only mid-afternoon here :)

PS: You might be getting the impression that I'm sounding a bit crabby, but
I'm not really.


"Brett" <no@xxxxxxxx> wrote in message
news:%234tqQ%23URFHA.3628@xxxxxxxxxxxxxxxxxxxxxxx
> Thanks Stephany. This is super helpful.
>
> Why is this part out of the loop:
> Dim networkStream As NetworkStream = tcpClient.GetStream()
>
> Also, your first IF:
> If networkStream.DataAvailable then
>
> didn't have an ending END IF. I put on just before the catch. Is that
> correct?
>
> This conditional is still being executed when returndata = ""
> If returndata <> "" AndAlso returndata <>
> ClientForm.ReturnData Then
> ClientForm.ReturnData = returndata
> End If
> Maybe I just don't understand the returndata = "" because of the byte
> array. But it seems you are testing the same conditions I did before. So
> the above will always execute because the array always has 8192 length and
> somehow that makes returndata pass on returndata <> "".
>
> How can I read the string in :
> Dim returndata As String = Encoding.UTF8.GetString(bytes, 0, bytesread)
> returndata gets the empty string here, although it really isn't, as have
> seen previously.
>
> thanks,
> brett
>
> "Stephany Young" <noone@localhost> wrote in message
> news:eJau0ZURFHA.576@xxxxxxxxxxxxxxxxxxxxxxx
>> The mist is clearing.
>>
>> If I've misunderstood anything please let me know because I'm still
>> making some assumptions.
>>
>> I suspect that your starting point for the Try ... Catch ... End Try
>> section is the example shown in the documentation on the
>> TcpClient.GetStream method.
>>
>> What you have done is wrapped it in a loop and added some embellishments
>> and that example was not quite designed for that to be done to it. The
>> example was designed for a one-time run and to drop through the logic to
>> whatever followed. In your case you want the loop to continue until
>> certain conditions are met or the program ends. To meet this need you
>> need to do things just a little differently.
>>
>> I assume that ClientForm.utility is also a shared reference to some sort
>> of utiliy class and that ClientForm.Packet is declared in a similar
>> fashion to ClientForm.ReturnData.
>>
>> If I am correct in that ConnectInit is outside the thread then you
>> shouldn't be attempting to reinstate a 'broken' connection within the
>> thread. If a 'broken' connection is detected you should allow the thread
>> to 'die', then reconnect, then start a new instance of the thread.
>>
>> Before the start of loop you are obtaining a reference to the
>> NetworkStream object of the TcpClient object. In addidition, on each
>> iteration of the loop you are obtaining a fresh reference to the
>> NetworkStream object of the TcpClient object. There is no reason to do
>> this. Don't quote me on this but I suspect that doing so will cause you
>> problems.
>>
>> The declaration of the 'bytes' array should not need to be inside the
>> loop. Creating a new array on every iteration is not necessary. When you
>> read the NetworkStream object, the data will overwrite what is already in
>> the array. of course the array should be created with 8192 elements by
>> using tcpClient.ReceiveBufferSize - 1 rather than the 8193 elements you
>> will get if you simply use tcpClient.ReceiveBufferSize.
>>
>> The NetworkStream.Read method, as well as filling the array, also returns
>> an integer indicating the number of bytes successfully read into the
>> array. You should make use of this to control what you are dealing with.
>> Remember that tcpClient.ReceiveBufferSize is the maximum number of bytes
>> that can be read at any one time rather than the number of bytes that are
>> actually read.
>>
>> For the third parameter to the NetworkStream.Read method, it is, in my
>> opinion, better to use bytes.Length rather than
>> tcpClient.ReceiveBufferSize because bytes.Length is the actual number of
>> elements in the array.
>>
>> I think that the tests of the NetworkStream.CanWrite and
>> NetworkStream.CanRead are probably redundant, unless you are opening the
>> sockets at either end with specfic read/write restrictions.
>>
>> Another important point is that the NetworkStream.Read method will block
>> until data is available. This is probably undesirable but can be
>> circumvented by using the NetworkStream.DataAvailable property. This will
>> allow your loop to iterate in a timely manner.
>>
>> Now that we know exactly how many bytes were read from the NetworkStream
>> object, we can use the appropriate Encoding.GetString overload to make
>> sure that our string is a representation of only those bytes. This should
>> do away with the need for any 'trimming' of the resulting string.
>>
>> Where you have the test for NetworkStream.DataAvailable is inappropriate
>> and I get the impression that you might not fully understand it's use.
>>
>> On the test of returndata, the .ToString is redundant because returndata
>> is already a string. The parenthesis are also redundant. In addition,
>> using AndAlso will be better than And here because if returndata is an
>> empty string then the second part of the test will not be evaluated if
>> AndAlso is used whereas it will be evaluated if just And is used. The
>> logic is that if the evaluation of first part fails then why bother
>> evaluating the second part at all. This is clled 'short-circuiting' and
>> is a very useful technique when used appropriately. Setting returndata to
>> Nothing is redundant because returndata is going to be created anew on
>> the next iteration of the loop. Likewise, the 'Else' that does nothing is
>> also redundant.
>>
>> As you can see, the resulting code is more compact and now, that the
>> appropriate techniques are being used, should work quite happily.
>>
>> What is left to do, of course, is for you to add the appropriate code to
>> 'tear-down' the thread in a friendly fashion when the program needs to
>> terminate or you need to stop the thread for some other reason.
>>
>>
>> Code as supplied by Brett
>> -------------------------
>>
>> In ClientForm
>> -------------
>> Public Shared ReturnData As String
>> Public Shared Packet As String ' or something like that
>> Public Shared utility As UtilityClass = New UtilityClass ' or something
>> like that
>> -------------
>>
>>
>> Dim ConnectAttempts As Integer = 0
>> Dim t As Thread
>>
>> Dim Packet As String
>> Dim InitialIDSent As Boolean = False
>>
>> Dim tsGap As TimeSpan
>> Dim dtStart As DateTime = Now
>>
>> ConnectInit()
>>
>> Within thread
>> -------------
>> Dim networkStream As NetworkStream = tcpClient.GetStream()
>>
>> While True
>> Try
>>
>> If networkStream.CanWrite And networkStream.CanRead Then
>>
>> networkStream = tcpClient.GetStream()
>>
>> Dim bytes(tcpClient.ReceiveBufferSize) As Byte
>> networkStream.Read(bytes, 0, tcpClient.ReceiveBufferSize)
>> Dim returndata As String =
>> Trim(Encoding.UTF8.GetString(bytes).Trim(Char.MinValue))
>>
>> 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)
>>
>> If networkStream.DataAvailable() Then
>> If (returndata <> "") And returndata.ToString <>
>> ClientForm.ReturnData Then
>> ClientForm.ReturnData = returndata
>> returndata = Nothing
>>
>> Else
>> End If
>> End If
>>
>> 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
>> Exit While
>> End Try
>>
>> Thread.CurrentThread.Sleep(500)
>> End While
>> -------------
>>
>>
>> Code as modified by Stephany
>> ----------------------------
>>
>> In ClientForm
>> -------------
>> Public Shared ReturnData As String
>> Public Shared Packet As String ' or something like that
>> Public Shared utility As UtilityClass = New UtilityClass ' or something
>> like that
>> -------------
>>
>>
>> Dim ConnectAttempts As Integer = 0
>> Dim t As Thread
>>
>> Dim Packet As String
>> Dim InitialIDSent As Boolean = False
>>
>> Dim tsGap As TimeSpan
>> Dim dtStart As DateTime = Now
>>
>> ConnectInit()
>>
>> Within thread
>> -------------
>> Dim networkStream As NetworkStream = tcpClient.GetStream()
>>
>> Dim bytes(tcpClient.ReceiveBufferSize - 1) As Byte
>>
>> Dim bytesread As Integer
>>
>> While True
>> Try
>> If networkStream.DataAvailable then
>> bytesread = networkStream.Read(bytes, 0, bytes.Length)
>> Dim returndata As String = Encoding.UTF8.GetString(bytes, 0,
>> bytesread)
>> 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)
>> If returndata <> "" AndAlso returndata <> ClientForm.ReturnData
>> Then ClientForm.ReturnData = returndata
>> End If
>> Catch ex As Exception
>> Exit While
>> End Try
>> Thread.CurrentThread.Sleep(500)
>> End While
>> -------------
>>
>>
>>
>
>


.



Relevant Pages

  • Re: Looping through Query to create multiple sheets in excel- Just need the loop
    ... I always get to this point and I can't figure out how to loop through ... I have put the string in the query at the bottom. ... Optional strWorkSheet As String, Optional strRange As ... Dim objXLSheet As Object 'Excel.Worksheet ...
    (microsoft.public.access.forms)
  • RE: Follow up question. Get value of closed file.
    ... MsgBox ReturnData and it said type mismatch. ... Dim ReturnData as Variant ... SourceSheet As String, _ ... Dim rsData As Object ...
    (microsoft.public.excel.programming)
  • Re: How is this conditional able to execute?
    ... > inside the loop, then each time the loop iterates then a NEW reference to ... > Note that the test of returndata is not a type. ... Here's some of my output starting with the first iteration: ... You can see returndata is the empty string above yet your IF is executed. ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How is this conditional able to execute?
    ... Why is this part out of the loop: ... Maybe I just don't understand the returndata = "" because of the byte array. ... How can I read the string in: ... > Dim t As Thread ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How to put lines with certain text (from a file) in an array
    ... In one sense all consistent but now the Filter approach is taking about 2x longer than the loop with Instr with all sizes. ... Dim sFile As String, sText As String ...
    (microsoft.public.excel.programming)