Results 1 to 10 of 10

Thread: Winsock randomly drops packets???

  1. #1

    Thread Starter
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Winsock randomly drops packets???

    Ok this is my problem:

    I have a client and a server app when i try to send winsock commands quickly ie:

    CLIENT:
    Code:
    Private function BulkTest()
        Winsock1.SendData "PlaySong"
        Winsock1.SendData "GetSongInfo"
    end function
    The server sends responses back (and does other stuff but that has been stripped for this eg):

    SERVER:
    Code:
    Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    Dim sData As String
        Winsock1.GetData sData
        Select Case LCase(sData)
            Case "playsong"
                Winsock1.SendData "OK:PlaySong"
            Case "getsonginfo"
                Winsock1.SendData "OK:GetSongInfo"
        End Select
    End Sub
    I would have thought that the client's Winsock1_DataArrival should run 2x in this case 1st with OK:PlaySong as the data and 2nd with OK:GetSongInfo, this is the case, most of the time.

    Occasionally however the clients Winsock1_DataArrival only fires once with the GetData returning both commands in one ie: OK:PlaySongOK:GetSongInfo

    Please help this is driving me mad

    Thanks in advance,
    Kris Bennett

  2. #2
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: Winsock randomly drops packets???

    Moved from Visual Basic Basic FAQs

  3. #3
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: Winsock randomly drops packets???

    There is a thing called buffering. With long lines you may also get it in two parts, it would be like:

    Packet 1: "OK:Play"
    Packet 2: "SongOK:GetSongInfo"

    To work around this, you can add end of line character, such as vbCrLf. This allows you to see when you don't have a complete line.

    Code:
    Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
        Dim sData As String, Dim sLine() As String, lA As Long
        Static sBuffer As String
        Winsock1.GetData sData
        ' include last buffer and split to a string array
        sLine = Split(sBuffer & sData, vbCrLf)
        ' process all strings except the last one
        For lA = 0 To UBound(sLine) - 1
            Select Case sLine(lA)
                Case "playsong"
                    Winsock1.SendData "OK:PlaySong" & vbCrLf
                Case "getsonginfo"
                    Winsock1.SendData "OK:GetSongInfo" & vbCrLf
            End Select
        Next lA
        ' set last incomplete line to buffer
        sBuffer = sLine(lA)
    End Sub

  4. #4
    Hyperactive Member
    Join Date
    Aug 2006
    Location
    TeXaS
    Posts
    497

    Re: Winsock randomly drops packets???

    here is an alterative to Post #3. i was bored :P
    the difference is, this lets winsock hold the buffer instead of use creating our own static variable.

    Code:
    Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
        
        Dim TmpStr As String
        Dim buffer() As String
        Dim i As Long
        
        Winsock1.PeekData TmpStr, vbString, bytesTotal
        buffer = Split(TmpStr, vbCrLf)
        If UBound(buffer) = 0 Then Exit Sub
        For i = 0 To UBound(buffer) - 1
            Select Case buffer(i)
                Case "playsong"
                    Winsock1.SendData "OK:PlaySong" & vbCrLf
                Case "getsonginfo"
                    Winsock1.SendData "OK:GetSongInfo" & vbCrLf
            End Select
        Next i
        'grab the data we need to remove from winsock buffer and do nothing
        Winsock1.GetData TmpStr, vbString, InStrRev(TmpStr, vbCrLf) + 1
        'the rest of the data from winsock is still saved in the winsock buffer
        
    End Sub

  5. #5
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Winsock randomly drops packets???

    True enough, but PeekData has been long deprecated as a performance problem and source of deadlocks.

    It results in nonpaged memory pool consumption which should not be a problem when there isn't much data being exchanged. Worse yet though, if you have large messages Winsock will "push back" and tell the other end to stop sending (part of TCP congestion control). If you have not buffered your "msg end" symbol in the underlying Winsock buffers when this happens everything just stops forever, because you'll never get it!

    This is a very bad habit to get into.

    The Lame List (see issues 12, 16). Issue 20 applies to the original question here.

    Worse yet, as coded you will risk discarding everything after the delimiter:
    It's common to use the GetData method with the DataArrival event, which includes the totalBytes argument. If you specify a maxlen that is less than the totalBytes argument, you will get the warning 10040 indicating that the remaining bytes will be lost.
    Last edited by dilettante; Aug 24th, 2008 at 01:35 PM.

  6. #6
    Hyperactive Member
    Join Date
    Aug 2006
    Location
    TeXaS
    Posts
    497

    Re: Winsock randomly drops packets???

    Quote Originally Posted by dilettante
    It results in nonpaged memory pool consumption which should not be a problem when there isn't much data being exchanged. Worse yet though, if you have large messages Winsock will "push back" and tell the other end to stop sending (part of TCP congestion control). If you have not buffered your "msg end" symbol in the underlying Winsock buffers when this happens everything just stops forever, because you'll never get it!

    This is a very bad habit to get into.
    i can see your point. "IF" you use large amounts of data. but as you can see, this example isnt, and i pity anyone that actually does. IMO you should never send over 2k of data in a packet.

    Quote Originally Posted by dilettante
    The Lame List (see issues 12, 16). Issue 20 applies to the original question here.

    Worse yet, as coded you will risk discarding everything after the delimiter:
    Quote:
    It's common to use the GetData method with the DataArrival event, which includes the totalBytes argument. If you specify a maxlen that is less than the totalBytes argument, you will get the warning 10040 indicating that the remaining bytes will be lost.
    ok issue #12: I do not "wait" for the rest of the data to arrive, i exit the sub and the event fires again when new data arrives. if i looped until the rest of the data arrived without exiting the procedure i can see that causing a problem.
    issue #16: Doesn't make any sense to me. the "It's redundant." doesn't really take the cake on an explanation. and about the error...if you are guaranteed another "FD_READ", then why would it even matter. the .GetData would have failed too and tried again later.
    issue #20:I don't think this applies to this example at all. My code does not assume that "bytesTotal" is the exact amount im receiving. It grabs what data it can using the bytestotal as a length to peek at. if bytestotal is not correct then vb is going to handle that internally when storing the data to my string. no issue there.

    and about the Warning of Bytes lost.. Apparently, the bytes are not lost, as you can see in the example. i have never lost bytes in all my testing. I have read this before in the MSDN and i do not agree with it as of yet. i think the winsock control has made this possible for us to use, despite the MSDN.

    If you could create an example of some underlying bug that would lose bytes using the sample i created, and not ruin merri's example as well; i would gladly reconsider your opinions. ty for your time.

  7. #7
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: Winsock randomly drops packets???

    That link is pretty interesting. I guess when I do further work with UniSock I'll also look through those guidelines and see if some parts could be done better (current problems: UDP does not work and IDE Stop safety has broken).

    Billy: the problem described by #12, as I understand it, is that you may lose buffers that have arrived. You only grab partial data with GetData, which means you have a partial buffer. This may lead to a problem that the following buffer may be lost, because that one does not get erased. It may be due to the various Winsock buffers not being one solid buffer, but many separate buffers. Thus in order to get the next one, you have to remove the earlier one entirely. dilettante probably has something to correct about this, my words here are mostly assumptions.
    Last edited by Merri; Aug 24th, 2008 at 03:09 PM.

  8. #8
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Winsock randomly drops packets???

    The problem with statements like "I have never seen a problem with this" is that you've just been lucky so far. Communication programming can be tough to thoroughly debug because it is hard to recreate all of the conditions that might occur in a real network. People have these same sorts of problems when using the MSComm control.

    Merri's example should be fairly solid under all conditions, assuming one also writes a decent handler for the Error event too.


    Those suggestions at The Lame List are expressed in some impolite terms, but they came about after years of answering the same questions and debugging the same problems. However they can be a little tough to interpret in terms of the Winsock control sometimes since they're expressed in regard to the underlying Winsock API.

    i can see your point. "IF" you use large amounts of data. but as you can see, this example isnt, and i pity anyone that actually does. IMO you should never send over 2k of data in a packet.
    *sigh* You are not sending "packets" when you use the Winsock control with a TCP connection. You are doing a send request with some data. These are not packets.

    And my point was to avoid forming bad habits or accumulating code samples to work from in the future that contain fatal flaws.

    As far as the send amount goes the fastest way to send a file via the Winsock control is to load the whole thing into a Byte array and blast it in one SendData call. People do this all the time. The Winsock control handles the outbound buffering for you. The only real downside is that you tie up that memory until all of the data is moved to outbound buffers and SendComplete is finally raised.

    To avoid this read in and send the data in chunks of 32K to 128K bytes, but usually this is only a concern for a server handling hundreds of connections.

    ok issue #12: I do not "wait" for the rest of the data to arrive, i exit the sub and the event fires again when new data arrives. if i looped until the rest of the data arrived without exiting the procedure i can see that causing a problem.
    Ahh, but you do wait. The waiting is waiting for a new DataArrival to occur, and the actual "wait" is in the Form's message loop.

    If you leave data in the buffer until you get your "end of message" delimiter, and enough data comes to fill up the socket's receive buffer, TCP will push back and not accept new data until your program removes some data from the buffer. Thus you have a Catch 22. No DataArrival will fire because no new data can arrive.
    Last edited by dilettante; Aug 24th, 2008 at 06:33 PM.

  9. #9
    Hyperactive Member
    Join Date
    Aug 2006
    Location
    TeXaS
    Posts
    497

    Re: Winsock randomly drops packets???

    ok, i see your point about having too much data and it not firing the event, but this should only happen if your client is not the official client that you programmed and is manipulating the data or if someone has set up a proxy and is sending packets thru it to screw up your parsing. a normal app will not do this because the data you send will be legit and it will find the EOM delimeter before it builds up too large. Basically, sending 125 byte packets or whatever should NEVER reach the state of which you are talking about unless it was purposely done. That being the case, you can look at it from another perspective. The .getdata will receive every packet, buffer it into the static variable, but it will be hogging up all of your memory because the packet still will not be parsed due to a lack of EOM; eventually collapsing the application from inefficient memory or an overflow.

    On another note. i have written quite a few applications that use peekmessage but do not require a delimeter. Actually i have never used a delimeter in any of my personal apps that i know of. I used it in this example to show a different way to have a buffer for incoming data. I personally have it wait for a specific amount of bytes to pass then copy it into a structure, from there i can tell if its a valid packet or not and discard it or handle it however need-be. this could not apply to having the buffer overflowing since im grabbing the 255 bytes or whatever is required no matter what it is when it arrives and leaving the rest there until it again builds up to 255 bytes.

  10. #10
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: Winsock randomly drops packets???

    If you think about it performance wise, there is no point using PeekData: you're getting the same data twice. In code length you're not saving anything. Also, when using a static variable in GetData event, you're only storing what remains after the last line change and Winsock's buffer is empty. If you want to protect against buffer overflowing, you simply check how big the buffer is and ignore the overflowing data until you get a new line change again. For example, in IRC protocol each line is limited to 512 characters, so anything more than that will be ignored. Client doesn't need to care about this so much, but a server must be protected (if it can be expected to be attacked).


    For an additional comparison here is what you can do with UniSock's text mode:
    Code:
    Private Sub Server_TextArrival(Text As String, ByVal LineChange As UniSockLineChange, ByVal ANSI As Boolean)
        Dim strLine As String
        ' process ANSI, if Unicode then the line is already processed to a VB string
        If ANSI Then strLine = StrConv(Text, vbUnicode) Else strLine = Text
        ' we are ready to process
        Select Case LCase$(strLine)
                ' UniSock automatically adds a line change with SendText
                Case "playsong"
                    Server.SendText "OK:PlaySong"
                Case "getsonginfo"
                    Server.SendText "OK:GetSongInfo"
        End Select
    End Sub
    You will get an individual event for each line. The line change is detected automatically (it can be CRLF, LF or CR). SendText defaults to UTF-8.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width