Results 1 to 8 of 8

Thread: Winsock byte array - need crash course *resolved

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Winsock byte array - need crash course *resolved

    Here's the code that sends the data.

    VB Code:
    1. 'This part is in another procedure
    2.     Select Case Left(strData, 20)
    3.     Case CM_QUERY_HOSTINFO
    4.         strSendData = CM_QUERY_HOSTINFO
    5.         Call SendData_sckTCP(SocketIndex, strSendData)
    6.        
    7.         MsgBox frmMainCommon.sckTCP(SocketIndex).State
    8.         If IntVar.Flag_IsServer = True Then
    9.             strSendData = CM_INFO_SERVERINFO & HostInfo_Local.B_UCDHostname
    10.             Call SendData_sckTCP(SocketIndex, strSendData)
    11.         Else
    12.             strSendData = CM_INFO_LOCALINFO & HostInfo_Local.B_UCDHostname
    13.             Call SendData_sckTCP(SocketIndex, strSendData)
    14.         End If
    15.  
    16.  
    17. 'This the generic send procedure
    18. Public Sub SendData_sckTCP(SocketIndex As Integer, strSendData As String)
    19. 'Procedure Description:
    20. '
    21.  
    22.     Dim Counter_SendAttempts As Byte
    23.     Dim strIPAddress_tmp As String
    24.    
    25.     Counter_SendAttempts = 0
    26.     strIPAddress_tmp = ""
    27.    
    28. On Error GoTo Error_Handler 'Enable error handler
    29.     frmMainCommon.sckTCP(SocketIndex).SendData strSendData
    30.  
    31. On Error GoTo 0             'Disable error handler
    32.     Exit Sub                'Exit function on successful send.
    33.  
    34. Error_Handler:
    35.     Counter_SendAttempts = Counter_SendAttempts + 1
    36.     If Counter_SendAttempts = MaxRetry_Send Then
    37.        
    38.         strIPAddress_tmp = IndexToIP_HostInfo_Array(SocketIndex)
    39.         MsgBox "Unable to send data to remotehost " & Trim(strIPAddress_tmp) & "." _
    40.             & vbCrLf & vbCrLf _
    41.             & "sckTCP(" & SocketIndex & ") will be unloaded and the corresponding" _
    42.             & vbCrLf & "host information will be removed from:" & vbCrLf _
    43.             & "     HostInfo_Array()" & vbCrLf _
    44.             & "     LoadedsckTCP_Array()", _
    45.             vbOKOnly, "Error: SendData_sckTCP(" & SocketIndex & ")"
    46.            
    47.         Call UnassignIndex_sckTCP(SocketIndex)
    48.         Call RemoveFrom_HostInfo_Array(strIPAddress_tmp)
    49.        
    50.         Resume Next
    51.     Else
    52.         Resume  'Retry send.
    53.     End If
    54.    
    55. 'Procedure Analysis:
    56. End Sub

    Instead of two data arrivals (which I had expected to happen);

    "CM_QUERY_HOSTINFO "
    "CM_INFO_SERVERINFO UC-Daisy "

    I got "CM_QUERY_HOSTINFO CM_INFO_SERVERINFO UC-Daisy "

    WHERE DID I GO WRONG! *sniff

    Is there anyway to make it two data arrivals? I want to avoid dealing with a stream as much as possible.

    Because if I do, I have to check amount of bytes before send, send that info along with the packet, parse the stream at the other end according to this, and so on and so forth... *sniff

    Can I use SendComplete in the solution, if so how?
    Last edited by leinad31; Feb 14th, 2003 at 11:38 AM.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629
    UnassignIndex_sckTCP(SocketIndex) essentially unloads the instance of the socket and updates UnloadedsckTCP_Array(). I keep track of the indexes I already used for reuse.

    RemoveFrom_HostInfo_Array(strIPAddress_tmp) updates the array where I keep the info on the remotehost.

    I don't think they have anything to do with the problem. Just in case your wondering.

  3. #3
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Well, believe it or not, that is how a socket works...

    The data that you send is a data stream, and if you send data at very short invervals, most of the data will be concatenated.

    You will have to set some logic in your program to split the data, for example put your message in [] like "[message]", then you will know where a message starts and where it ends...

    The way I do it is I send the length of how much is to send, something like "10:asdfghjklp", so then the program on the receiving side, it know how much data to expect, and if you send a lot of data like "100000:sdfsdfaf... etc" then the client can buffer all data until it gets 100000 bytes, then it will use the data...

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629
    I was doing some research while waiting for a reply and I realized so... Oh well.

    So what's the best approach? I was already considering making a trailer to complement the header. But it opens a can of worms if the user sends a message containing the header and/or trailer info.

    Same with bytes total. What if they type "100000:sdfsdfaf" into the message. It will screw up the parser unless I make the parser very complex.

    Is it possible to send a structure instead of a plain string?

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629
    I think I've figured out a way to ignore the data/user message when parsing. Wish me luck

  6. #6
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Good luck

    But...
    Even if the user types something like "5:12345", your program will send: "7:5:12345"

    all you have to do is to get the number from the first ":" and read the given length as the message
    So
    it will read the length 7, and then it will take the next 7 characters as the message 5:12345

    So it works always, it does not matter what they type because your number will always be first...

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629
    I'll go with that. But I also plan to implement file transfer in the same connection. Since I'm using a generic send procedure I'll need to convert everything into a bit array. While I figure out the general design of the parser and anything else I have to redesign, can you give me a crash course on bit arrays in relation to winsock?

    Major points would be:
    - Is a character 8 bits, 16 bits, or OS dependent (the thought gives me a headache)?
    - Converting a string to byte array, and vice versa.
    - With your header suggestion, do I count total bytes or bits?
    - Related to the above, when I load a file, its in chunks of 1 byte, right (haven't coded it yet)?
    - And some other important pointers on bit array manipulation.
    Last edited by leinad31; Feb 13th, 2003 at 04:42 PM.

  8. #8
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    How to open and read the data from the file (can be any file type, even binary)
    VB Code:
    1. dim Buffer as string
    2.  
    3. open "myfile.dat" for binary access read lock write as #1
    4.     buffer = String(lof(1), 0)
    5.     Get #1, , buffer
    6. Close #1

    Now the thing is, when you send large amounts of data (over 1KByte), you need to break it down into smaller chunks

    So... you have to send 1K, then wait until the data is sent, then send the other 1k and so on...

    the hard part is that you cannot do this in one function since you have to do all the waiting...

    first make a function that openes a file and sends the first 1K
    then in the winsock1_SendComplete event you have to send the other 1K...

    now there is another problem

    You cannot do "winsock1.SendData myData" inside the SendComplete event.... winsock will give you and error because the sendcomplete function HAS to end it code, then you have to send the data

    now, the only option is a timer set to interval of 1 (1 millisecond)

    so...
    here's the pseudocode...

    add a timer on the form with interval = 1 and enabled = false
    VB Code:
    1. ' globals
    2. const bufflen as long = 1024
    3. dim filenumber as integer
    4.  
    5.  
    6. ' open file and send 1K
    7. private sub SendFile(byval myFile as string)
    8. dim buffer as string
    9.  
    10. filenumber = freefile
    11. open myFile for binary access read lock write as filenumber
    12. buffer = string(bufflen, 0)
    13. get filenumber, , lof(filenumber) & ":" & buffer
    14. Winsock1.Send buffer
    15.  
    16. end sub
    17.  
    18.  
    19.  
    20. private sub winsock1_SendComplete()
    21.    ' start the timer to send the next 1K
    22.    timer1.interval = 1
    23.    timer1.enabled = false
    24.    timer1.enabled = true
    25. end sub
    26.  
    27.  
    28.  
    29. private sub timer1_timer()
    30. dim buffer as string
    31.  
    32. if loc(filenumber) + bufflen > lof(filenumber) then
    33.    ' this is the last packet
    34.    buffer = string(lof(filenumber) - loc(filenumber), 0)
    35. else
    36.    bufer = string(bufflen, 0)
    37. endif
    38.  
    39. get filenumber, , buffer
    40. winsock1.senddata buffer
    41.  
    42. if len(buffer) < bufflen or loc(filenumber) >= lof(filenumber) then
    43.    ' close the file if no more data to send
    44.    close filename
    45. endf
    46.  
    47. ' ALWAYS set it to false, because if not, it will send the next 1K
    48. ' without waiting until the current packet is sent
    49. timer1.enambled = false
    50. end sub

    hope this helps...
    Last edited by CVMichael; Feb 13th, 2003 at 04:58 PM.

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