Re: How is this conditional able to execute?




"Stephany Young" <noone@localhost> wrote in message
news:ucW30eVRFHA.3496@xxxxxxxxxxxxxxxxxxxxxxx
> 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.
>

To leave the end if off is to get a compiler error. I don't know how you
are able to compile without. Perhaps you didn't paste all of the code?

> 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.

I see this in the output and watches windows. I can also see it when I
mouse over the variable.

I did try to run some previous code but received an error. I don't think
you saw my reply to it:

Console.Writeline("mystring.Length = {0}", mystring.Length)
For _i As Integer = 0 To mystring.Length
Select Case CType(mystring.Chars(_i), Integer)
Case Is < 32, Is > 126
Console.Writeline("Character {0} found at position {1}",
CType(mystring.Chars(_i), Integer), _i)
End Select
Next

I pasted in the above but get the following error on both occurances of the
following:
mystring.Chars(_i)

'Char' values cannot be converted to 'Integer'. Use
'Microsoft.VisualBasic.AscW' to interpret a character as a unicode value or
'Microsoft.Visualbasic.Val' to interpret it as a digit.

>
> 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)
>

Here's some of my output starting with the first iteration:

returndata.length = 36
returndata = Connection accepted:06:52:56.5599165
Changing
ClientForm.ReturnData = Connection accepted:06:52:56.5599165
returndata.length = 8192
Changing
ClientForm.ReturnData = Unable to write data to the transport
connection.Connected: BrettsLaptop 192.168.2.251returndata = Unable to write
data to the transport connection.Connected: BrettsLaptop
192.168.2.251returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 5641
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing
ClientForm.ReturnData = returndata = returndata.length = 8192
Changing

You can see returndata is the empty string above yet your IF is executed.
Meaning, it's saying If returndata <> "". Correct?

> 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.

Check the above output.

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

It does a filewatch and will send back a file path if certain files has been
modified.

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

Couldn't help it last night. The last few nights caught up with me.

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

You in Europe Stephany?

>
>
> "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: 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. ... Dim returndata As String = "" ... Not that 'Changing' is only displayed when returndata is NOT an empty string ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Get_Line problem (GNAT bug?)
    ... If the behavior is defined to support iteration ... A while loop, probably, or something in this area. ... I am using exceptions for parsing sources. ... But Get_Line already has a result, which is a string. ...
    (comp.lang.ada)
  • 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: URI Escape/Unescape Library?
    ... >> I also replaced the loop and length with DOTIMES. ... > binding of var on each iteration or whether it establishes a ... characters instead of iterating over the string. ...
    (comp.lang.lisp)
  • Re: How is this conditional able to execute?
    ... >>> inside the loop, then each time the loop iterates then a NEW reference ... >>> Note that the test of returndata is not a type. ... >>> will evaluate to False and the conditional code will NOT be executed. ... >> You can see returndata is the empty string above yet your IF is executed. ...
    (microsoft.public.dotnet.languages.vb)