|
-
Feb 13th, 2003, 12:11 PM
#1
Winsock byte array - need crash course *resolved
Here's the code that sends the data.
VB Code:
'This part is in another procedure
Select Case Left(strData, 20)
Case CM_QUERY_HOSTINFO
strSendData = CM_QUERY_HOSTINFO
Call SendData_sckTCP(SocketIndex, strSendData)
MsgBox frmMainCommon.sckTCP(SocketIndex).State
If IntVar.Flag_IsServer = True Then
strSendData = CM_INFO_SERVERINFO & HostInfo_Local.B_UCDHostname
Call SendData_sckTCP(SocketIndex, strSendData)
Else
strSendData = CM_INFO_LOCALINFO & HostInfo_Local.B_UCDHostname
Call SendData_sckTCP(SocketIndex, strSendData)
End If
'This the generic send procedure
Public Sub SendData_sckTCP(SocketIndex As Integer, strSendData As String)
'Procedure Description:
'
Dim Counter_SendAttempts As Byte
Dim strIPAddress_tmp As String
Counter_SendAttempts = 0
strIPAddress_tmp = ""
On Error GoTo Error_Handler 'Enable error handler
frmMainCommon.sckTCP(SocketIndex).SendData strSendData
On Error GoTo 0 'Disable error handler
Exit Sub 'Exit function on successful send.
Error_Handler:
Counter_SendAttempts = Counter_SendAttempts + 1
If Counter_SendAttempts = MaxRetry_Send Then
strIPAddress_tmp = IndexToIP_HostInfo_Array(SocketIndex)
MsgBox "Unable to send data to remotehost " & Trim(strIPAddress_tmp) & "." _
& vbCrLf & vbCrLf _
& "sckTCP(" & SocketIndex & ") will be unloaded and the corresponding" _
& vbCrLf & "host information will be removed from:" & vbCrLf _
& " HostInfo_Array()" & vbCrLf _
& " LoadedsckTCP_Array()", _
vbOKOnly, "Error: SendData_sckTCP(" & SocketIndex & ")"
Call UnassignIndex_sckTCP(SocketIndex)
Call RemoveFrom_HostInfo_Array(strIPAddress_tmp)
Resume Next
Else
Resume 'Retry send.
End If
'Procedure Analysis:
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.
-
Feb 13th, 2003, 12:17 PM
#2
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.
-
Feb 13th, 2003, 12:55 PM
#3
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...
-
Feb 13th, 2003, 01:04 PM
#4
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?
-
Feb 13th, 2003, 01:32 PM
#5
I think I've figured out a way to ignore the data/user message when parsing. Wish me luck
-
Feb 13th, 2003, 03:19 PM
#6
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...
-
Feb 13th, 2003, 04:32 PM
#7
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.
-
Feb 13th, 2003, 04:55 PM
#8
How to open and read the data from the file (can be any file type, even binary)
VB Code:
dim Buffer as string
open "myfile.dat" for binary access read lock write as #1
buffer = String(lof(1), 0)
Get #1, , buffer
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:
' globals
const bufflen as long = 1024
dim filenumber as integer
' open file and send 1K
private sub SendFile(byval myFile as string)
dim buffer as string
filenumber = freefile
open myFile for binary access read lock write as filenumber
buffer = string(bufflen, 0)
get filenumber, , lof(filenumber) & ":" & buffer
Winsock1.Send buffer
end sub
private sub winsock1_SendComplete()
' start the timer to send the next 1K
timer1.interval = 1
timer1.enabled = false
timer1.enabled = true
end sub
private sub timer1_timer()
dim buffer as string
if loc(filenumber) + bufflen > lof(filenumber) then
' this is the last packet
buffer = string(lof(filenumber) - loc(filenumber), 0)
else
bufer = string(bufflen, 0)
endif
get filenumber, , buffer
winsock1.senddata buffer
if len(buffer) < bufflen or loc(filenumber) >= lof(filenumber) then
' close the file if no more data to send
close filename
endf
' ALWAYS set it to false, because if not, it will send the next 1K
' without waiting until the current packet is sent
timer1.enambled = false
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|