NetworkStream .Write() method not completing

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • JeremyH

    NetworkStream .Write() method not completing

    I'm trying to create a simple, synchronous TCP client program to
    receive requests and return data. My code very closely resembles the
    example code provided in the Help files, but I find that the .Write
    method - when run at full speed - only seems to successfully write
    data the first time it is called.

    For testing purposes, I am using Hyperterminal on another computer to
    send 4 characters. The program always successfully reads all 4
    characters. It is then supposed to reverse them and send the reversed
    byte array back. Here is the code:

    Private tcpLstn As New TcpListener(511 12)

    Public Sub subMainLoop()
    Dim tcpClnt As TcpClient
    Dim ns As NetworkStream
    Dim buffr(4) As Byte
    Dim buffr2(6) As Byte
    Dim iRead As Integer

    bScan = True

    tcpLstn.Start()

    While bScan
    '--- Code execution pauses here until TCP connection
    request
    '--- is received.
    tcpClnt = tcpLstn.AcceptT cpClient()

    ns = tcpClnt.GetStre am()

    '--- Wait until 4 characters are successfully read
    iRead = 0
    While iRead < 4
    iRead = iRead + ns.Read(buffr, iRead, 4 - iRead)
    End While

    '--- Create array of characters to send back
    buffr2(0) = 13
    buffr2(1) = 10
    buffr2(2) = buffr(3)
    buffr2(3) = buffr(2)
    buffr2(4) = buffr(1)
    buffr2(5) = buffr(0)

    Try
    '--- Send requested data over TCP port
    ns.Write(buffr2 , 0, 6)
    ns.Close()
    tcpClnt.Close()
    Catch e As Exception
    Console.WriteLi ne(e.ToString() )
    End Try

    '--- Process events
    Application.DoE vents()
    End While

    tcpLstn.Stop()

    End Sub


    When stepping through in debug mode, the ns.Write(buffr2 , 0, 6)
    command works about 95% of the time, and the returned characters are
    displayed in HyperTerminal. When running the program with no breaks
    and no MsgBox calls in the main loop, the program only successfully
    writes back the 4 characters (plus {LF}{CR}) the first time. From
    HyperTerminal (and other testing methods) I can tell that the 4
    characters I send ARE, in fact, being read by the program EVERY time.
    The response simply isn't coming through.

    Ultimately, the program is only ever going to be communicating with
    one other computer. So there isn't any need for multi-threading or
    asynchronous reading/writing.

    Am I missing something, though?
  • JeremyH

    #2
    RE: Solution Found

    I can't believe that in this day in age there are still inherent timing issues/bugs in released development classes. This is RETARDED!!

    The problem, it turns out, is that the NetworkStream .Write() method returns IMMEDIATELY. It does NOT wait until the data has actually been sent. Microsoft claims that it returns after making sure the data was added to the STREAM. This may be the case. However, there is no guarantee that the stream has actually been sent before closing the connection

    My code reads like this
    ...
    ns.Write(buffr2 , 0, 6
    ns.Close(
    tcpClnt.Close(
    ...

    Problem was: ns.Close() and tcpClnt.Close() were getting called before the data stream was actually sent - i.e. the underlying socket got closed before completing pending data transmissions. The code is/will be running on a P4 1.8GHz+ processor. The fix was to put in a manual loop delay (which any decent program should NEVER have to resort to) right after the ns.Write() command. This is a sucky solution, but the only one that works

    ...
    ns.Write(buffr2 , 0, 6
    For i = 1 to 100000
    i =
    Nex
    ns.Close(
    tcpClnt.Close(
    ...

    I tried enabling tcpClnt.LingerS tate, setting tcpClnt.NoDelay = True, raising the tcpClnt.LingerT ime, making sure the .SendBuffer was set low since I am only sending 6 bytes at a time - but none of those things made any difference. THE ONLY WAY to avoid the timing limitation on sending data is to create a manual delay or have other code executing before calling the .Close() methods

    Someone needs to put this in a book/article somewhere

    Comment

    • JeremyH

      #3
      RE: Solution Found

      I can't believe that in this day in age there are still inherent timing issues/bugs in released development classes. This is RETARDED!!

      The problem, it turns out, is that the NetworkStream .Write() method returns IMMEDIATELY. It does NOT wait until the data has actually been sent. Microsoft claims that it returns after making sure the data was added to the STREAM. This may be the case. However, there is no guarantee that the stream has actually been sent before closing the connection

      My code reads like this
      ...
      ns.Write(buffr2 , 0, 6
      ns.Close(
      tcpClnt.Close(
      ...

      Problem was: ns.Close() and tcpClnt.Close() were getting called before the data stream was actually sent - i.e. the underlying socket got closed before completing pending data transmissions. The code is/will be running on a P4 1.8GHz+ processor. The fix was to put in a manual loop delay (which any decent program should NEVER have to resort to) right after the ns.Write() command. This is a sucky solution, but the only one that works

      ...
      ns.Write(buffr2 , 0, 6
      For i = 1 to 100000
      i =
      Nex
      ns.Close(
      tcpClnt.Close(
      ...

      I tried enabling tcpClnt.LingerS tate, setting tcpClnt.NoDelay = True, raising the tcpClnt.LingerT ime, making sure the .SendBuffer was set low since I am only sending 6 bytes at a time - but none of those things made any difference. THE ONLY WAY to avoid the timing limitation on sending data is to create a manual delay or have other code executing before calling the .Close() methods

      Someone needs to put this in a book/article somewhere

      Comment

      Working...