|
-
Mar 31st, 2004, 05:25 AM
#1
Winsock question...
When you send data using winsock the code execution carries on to the code once the data has been sent, regardless if it's been received or not by the server winsock connection.
Is it possible, WITHOUT writting wrapper classes, to use the SendData sub like a function...ie, you send data, but code execution stops until the server app sends data back to the client winsock??
Woka
-
Mar 31st, 2004, 09:11 AM
#2
Registered User
can't you have a timer control in there somewhere, and then when your waiting for data to come back have it loop in the timer control for data on that index only
-
Mar 31st, 2004, 09:14 AM
#3
You could do something like that, but it would be a cheap hack. You could not add something like that into a commercial app.
I don't have an array of winsocks...as this is also bad coding for a commercial app. I spawn new threads in VB and have specialised connections in each thread.
Woka
-
Mar 31st, 2004, 10:33 AM
#4
Frenzied Member
Re: Winsock question...
Originally posted by Wokawidget
When you send data using winsock the code execution carries on to the code once the data has been sent, regardless if it's been received or not by the server winsock connection.
Is it possible, WITHOUT writting wrapper classes, to use the SendData sub like a function...ie, you send data, but code execution stops until the server app sends data back to the client winsock??
Woka
Make everything event driven. For example:
1) A "Send" button click calls routine to connect to server.
2) The Winsock_Connect event sub will build & send the request.
3) The Winsock_DataArrival event sub will read the reply data and process it, then close the connection.
If coded correctly, nothing will happen until an event occurs.
Of course, this is a very simplistic example. What exactly do you want to do?
-
Mar 31st, 2004, 10:34 AM
#5
Re: Winsock question...
Originally posted by Wokawidget
When you send data using winsock the code execution carries on to the code once the data has been sent, regardless if it's been received or not by the server winsock connection.
Is it possible, WITHOUT writting wrapper classes, to use the SendData sub like a function...ie, you send data, but code execution stops until the server app sends data back to the client winsock??
Woka
perhaps you can divide the execting code into 2 subs (or functions) and call the one which sends the data via winsock, and then all the rest of the code to be executed put into the second sub/function. call it on the data arrival event of the winsock if the data coming back is the data you were waiting for... avoids the timers and loops
-
Mar 31st, 2004, 10:48 AM
#6
Fanatic Member
What you're saying is implementation specific, meaning it is upto you. One implementation below:
CLIENT
Code:
Private Sub Form_Load()
Dim Subordinate As User
Me.MousePointer = vbHourglass
Call IResizesChildren_ResizeChildren
BoolSubordinatesListReceived = False
BoolJobTransferWindowRequestingConnection = True
Call SendSubordinateListRequest
Do
DoEvents
If BoolServerOffline Then
BoolJobTransferWindowRequestingConnection = False
Me.MousePointer = vbDefault
Exit Sub
End If
Loop Until BoolSubordinatesListReceived Or BoolServerOffline
If colSubordinates Is Nothing Then
OurMessageBox "It is not possible to execute this task because there are currently no subordinates in your team." _
, vbInformation, App.Title
BoolSubordinatesListReceived = False
Unload Me
Exit Sub
Else
cboFromUser.Clear
cboFromUser.AddItem vbNullString
For Each Subordinate In colSubordinates
cboFromUser.AddItem Subordinate.FullName
Next Subordinate
BoolSubordinatesListReceived = False
Me.MousePointer = vbDefault
End If
End Sub
Public Sub SendSubordinateListRequest()
Dim StrMessageToSend As String
StrMessageToSend = ComposeMessage(MgrSubordinatesRequest)
Call mdiNew.SendMessageToServer(StrMessageToSend)
End Sub
Public Sub SendMessageToServer(ByVal StrMessageToSend As String)
Dim LngTime As Long
Internet.Connect
BoolWinsockStillConnecting = True
BoolServerOffline = False
LngConnectionAttempts = 0
LngTime = Timer
Do
LngConnectionAttempts = LngConnectionAttempts + 1
If Wsock.State <> sckConnected Then
If Wsock.State <> sckClosed Then Wsock.Close
Wsock.Protocol = sckTCPProtocol
Wsock.RemotePort = SERVER_PORT
Wsock.RemoteHost = StrServerIPAddress
Wsock.Connect
End If
Do
DoEvents
If BoolServerOffline Then BoolWinsockStillConnecting = False: Exit Sub
If BoolForceQuit Then Call ExitApplication
Loop Until Wsock.State = sckConnected Or Timer >= (LngTime + (LngConnectionAttempts * 5))
If IsLoaded("frmLogin") Then Call frmLogin.ClearProgressBar
If LngConnectionAttempts = 3 Then
OurMessageBox "It is not possible to connect to the server at this time due to network congestion. Please try again later.", vbInformation, App.Title
BoolWinsockStillConnecting = False
If IsLoaded("frmLogin") Then frmLogin.Hide: BoolForceQuit = True: Call ExitApplication
Exit Sub
End If
Loop Until Wsock.State = sckConnected
BoolWinsockStillConnecting = False
StrMessageToSend = PacketMessage(Encrypt(StrMessageToSend))
Wsock.SendData StrMessageToSend
End Sub
SERVER
Code:
Private Sub WSock_DataArrival(Index As Integer, ByVal bytesTotal As Long)
On Error GoTo ErrorDataArrival
Dim StrMessageRecieved As String
Dim StrMessageToSend As String
Dim Arr() As String
Dim I As Long
Dim LngCounter As Long
WSock(Index).GetData StrMessageRecieved, vbString
StrMessageRecieved = UnpacketMessage(StrMessageRecieved)
Arr = Split(StrMessageRecieved, PACKET_END)
If UBound(Arr) < 0 Then Exit Sub
For LngCounter = 0 To UBound(Arr)
StrMessageRecieved = Arr(LngCounter)
StrMessageRecieved = Decrypt(StrMessageRecieved)
If Trim(StrMessageRecieved) = vbNullString Then GoTo NextMessage
If Trim(StrMessageRecieved) <> vbNullString Then Set Message = ParseMessage(StrMessageRecieved)
If Message Is Nothing Then GoTo NextMessage
SocketPool(Index).UserName = Message.UserName
MDI.sbrPrintMate.Panels("sbrpnlTransactionProgress").Text = GetMessageTypeString(Message.MessageType) & _
" recieved from " & Message.UserName
If Message.MessageType = DataBaseQuery Then
Call SaveToRepository(Message.MessageData.DataBaseQuery.DataBaseQueryString, InBound, DataBaseQuery, Message)
ElseIf Message.MessageType = LoginAuthRequest Or Message.MessageType = MgrSubordinatesRequest Then
'Do nothing
ElseIf Message.MessageType = UserProfileResponseReadReceipt _
Or Message.MessageType = UserActiveStatusResponseReadReceipt _
Or Message.MessageType = UserRightsResponseReadReceipt _
Or Message.MessageType = DataBaseQueryReadReceipt Then
Call ClearMessageFromRepository(OutBound, Message.MessageID, Message.UserName)
ElseIf Message.MessageType = JobTransferRequest Then
'Save the request to the database
If Not SaveJobTransfer(Message.MessageData.JobTransferRequest.FromUser, _
Message.MessageData.JobTransferRequest.ToUser, Message.UserName, _
Message.MessageData.JobTransferRequest.CompanyList) Then
Debug.Print String(300, "=")
Debug.Print "Failed to save job transfer request in the database. Details of the job transfer request are: "
Debug.Print "From User: " & Message.MessageData.JobTransferRequest.FromUser
Debug.Print "To User: " & Message.MessageData.JobTransferRequest.ToUser
Debug.Print "Manager: " & Message.UserName
For I = 1 To Message.MessageData.JobTransferRequest.CompanyList.Count
Debug.Print Message.MessageData.JobTransferRequest.CompanyList.Item(LngCounter).CompanyName
Next I
Debug.Print String(300, "=")
End If
'The intimation to both users shall be given in the SynchronizeData method
End If
Set Reply = CreateReply(Message)
StrMessageToSend = ComposeMessageString(Reply)
MDI.sbrPrintMate.Panels("sbrpnlTransactionProgress").Text = "Sending " & GetMessageTypeString(Reply.MessageType) & _
" to " & Reply.UserName
If StrMessageToSend <> vbNullString Then
StrMessageToSend = PacketMessage(Encrypt(StrMessageToSend))
WSock(Index).SendData StrMessageToSend
If Message.MessageType <> DataBaseQuery Then DoEvents
End If
NextMessage:
Next LngCounter
If BoolAutomaticallySynchronize Then Call SynchronizeData
ErrorDataArrival:
If Err <> 0 Then
If Err = RECEIVED_DATA_AFTER_CLIENT_WENT_OFFLINE Then
MDI.sbrPrintMate.Panels("sbrpnlTransactionProgress").Text = "Communication Error: " & _
"The user " & SocketPool(Index).UserName & " has just gone offline. " & _
"Cannot parse data received from the user. Data abandoned."
End If
End If
End Sub
-
Mar 31st, 2004, 11:09 AM
#7
Good...but not good enough...while looping to see if data has been retrieved then your UI stops repainting 
I have code that does it, I just wanted to know if WINSOCK did it, WITHOUT writting code to loop it.
I currently create another thread in VB and use that to send data and loop. Since it's in another thread then my main app can be repainted and doesn't look as if it's crashed.
Using the SendMessage API halts the code execution until my thread returns the servers response.
Woka
-
Mar 31st, 2004, 12:48 PM
#8
Registered User
sorry this is alittle off topic, but is this what i would need to do to have clients connect to a server app and such? i need to use winsock and threads... but dont know how
-
Mar 31st, 2004, 12:54 PM
#9
Fanatic Member
>...while looping to see if data has been retrieved then your UI stops repainting
That is not true. You don't actually need multithreading here, really, to be honest. A DoEvents does suffice, unless you want fine grained control over what the user must be allowed to do within that timeframe the data is being sent.
-
Mar 31st, 2004, 01:15 PM
#10
Registered User
I had read in a thread that using DoEvents in a winsock precedure is not recommended, it will cause winsock to be buggy or something i think.... bottom line is i heard it wasnt good to use
plus doevents will just call a timer control if it's present, and time controls were said to work but it's not to be used for commercial apps, so doevents wont work
-
Mar 31st, 2004, 01:57 PM
#11
Originally posted by krpto
I had read in a thread that using DoEvents in a winsock precedure is not recommended, it will cause winsock to be buggy or something i think.... bottom line is i heard it wasnt good to use
plus doevents will just call a timer control if it's present, and time controls were said to work but it's not to be used for commercial apps, so doevents wont work
doevents would only cause a timer to fire if there was one.. which there is not.. i think you may have misread
-
Mar 31st, 2004, 03:20 PM
#12
Fanatic Member
Originally posted by Wokawidget
Good...but not good enough...while looping to see if data has been retrieved then your UI stops repainting 
I have code that does it, I just wanted to know if WINSOCK did it, WITHOUT writting code to loop it.
Woka
Winsock has no built in support for what you want; try to work with winsock, not against it. If something isn't supported by winsock (I really mean the API/DLL here, not the rather basic functionality of the control), there's probably a good reason.
You could do something like that, but it would be a cheap hack. You could not add something like that into a commercial app.
I don't have an array of winsocks...as this is also bad coding for a commercial app. I spawn new threads in VB and have specialised connections in each thread.
Hmm. Why is a multithreading solution any "better" than a winsock array? How do you do the I/O in the threads, control or API?
Be wary of threads, e.g. a thread-per-connection model will scale extremely poorly..threads shouldn't be overused.
-
Mar 31st, 2004, 11:23 PM
#13
Member
>>threads shouldn't be overused.
Apparently, if you have too many more threads than processors, you lose a lot of performance from too many context switches (or something of the like... I'm just parroting something I heard.) 
>>Winsock has no built in support for what you want
If you're talking about the DLL, I'm not sure if that's true, since with the C++ API calls, sockets are automatically put in 'blocking' mode when they're created. But, generally, you avoid blocking like the plague (i.e. you manually set the mode to asynchronous/non-blocking), which I suppose is why the VB control doesn't even support it. You'd be much better off making your own function/procedure to do background processing while periodically checking to see if the operation has completed.
writing software in C++ is like writing software in VB, except that it's slower and harder and more frustrating and more finicky and doesn't give you nice convenient shortcuts on a silver platter. And it's better. *puts on heat-reflecting armor*
-
Apr 1st, 2004, 06:38 AM
#14
Fanatic Member
If you're talking about the DLL, I'm not sure if that's true, since with the C++ API calls, sockets are automatically put in 'blocking' mode when they're created.
Yes, but for example a call to send() blocks until your supplied buffer has been accepted by winsock; the data has not necessarily been sent when the send() call returns. To have a function that doesn't return until a response has been received, you'd call a blocking send() followed by a blocking recv(). However, requiring such a function hints at the design of the program being less than optimal.
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
|