[RESOLVED] winsock multi-user chat: Change index value of control at runtime
The major problem that i have been stuck with is when a client disconnects from the server, the connection is closed and the control is unloaded.
when i try to send new information to other clients i am using a "For next" loop, however when i do this, it will error because one of the connections is not connected at the time.
i searched on google to see if i could change the index property of a control at runtime so that i can fix the control array so that there is no gaps, but after looking i don't think you can change that value..
what would be the easiest way to do this? to handle when a user leaves the chat and so that the server can still send messages to all connected clients.
Re: winsock multi-user chat: Change index value of control at runtime
Welcome to VBForums :wave:
One solution is rather than using a For loop, use a For-Each, eg:
Code:
Dim objWinsock as Winsock
For Each objWinsock In Winsock1 'change to the name of your array
'use objWinsock here, rather than Winsock1(x)
Next objWinsock
Re: winsock multi-user chat: Change index value of control at runtime
Actually it is better not to unload Winsock controls.
The simple approach is for a new connection request to scan the existing control array for an open slot (control that has State = sckClosed) and then use that. Only if you run out of controls would you Load a new one at the end and use it.
For a long-running server you might even get trickier. Every time a user connects do this scan-and-add as described. However if you didn't Load a new instance do a backward scan of the control array. If you find at least 3 (or 5, etc.) unused slots at the end Unload them to free resources.
Note that unless you are using the VB6 SP6 version of the Winsock control there is a memory leak when you unload them! This was once a serious problem for long-running servers, but it was fixed somewhere from SP5 to SP6. Always use the SP6 control. It is probably the last version we'll ever see and a very large number of improvements were made over the years, most of them applying to use in servers.
Re: winsock multi-user chat: Change index value of control at runtime
Thanks for the welcome :) and thanks so much for the quick reply.
i'm pretty sure that will fix my problem but at the moment i am using a variable to determine how many connections i have so when a user connects they will connect to Winsock(Variable) rather than any connection available
is there a way of making a new control with an index closest to 1 as possible that doesn't already have a connection?
Edit: dilettante answered my question thanks very much, i was just late to reply this post hehe.. I will now search the forums on how to search for an unused loaded winsock, thank you very much :)
Re: winsock multi-user chat: Change index value of control at runtime
Ok so i know this code is a bit messy.. but it works for me, it now just error traps 340 (which is saying a control doesn't exist) so therefore it creates one otherwise it loops through the other connections and if it finds one with a state not connected, it accepts the requestID to that connection.
Code:
Private Sub sockUser_ConnectionRequest(Index As Integer, ByVal requestID As Long)
Dim Attempt As Integer
Attempt = 1
On Error GoTo t
k:
If sockUser(Attempt).State = sckConnected Then
Attempt = Attempt + 1
GoTo k
Else
sockUser(Attempt).Accept requestID
UserCounter = UserCounter + 1
Exit Sub
End If
t:
If Err.Number = 340 Then
Load sockUser(Attempt)
sockUser(Attempt).Accept requestID
UserCounter = UserCounter + 1
Exit Sub
End If
End Sub
Re: [RESOLVED] winsock multi-user chat: Change index value of control at runtime
Here is a tidied version of that, using the method shown in the FAQ article How do I detect if an index exists in a control array?:
Code:
Private Sub sockUser_ConnectionRequest(Index As Integer, ByVal requestID As Long)
Dim Attempt As Integer
For Attempt = 1 To sockUser.UBound
If VarType(sockUser(Attempt)) = vbObject Then 'check if array index is not in use
Load sockUser(Attempt)
End If
If sockUser(Attempt).State <> sckConnected Then
sockUser(Attempt).Accept requestID
UserCounter = UserCounter + 1
Exit Sub
End If
Next Attempt
End Sub
You should ideally add an error handler to this to deal with any unexpected errors somehow.
Re: [RESOLVED] winsock multi-user chat: Change index value of control at runtime
Thanks very much Si, i recently logged on and checked through my old posts to find this.
I used your code, thanks very much, but there were a few things wrong with it that i had to fix.
First of all: For Attempt = 1 to sockUser.Ubound is the same as For Attempt = 1 to 0 which does not start the loop.
Second For Attempt = 0 to sockUser.UBound + 1 does not work as when i try sockUser(0).Accept request ID it comes up with an Error "Invalid operation at current state".
So I fixed that issue by avoiding index 0 completely, so now my code is:
For Attempt = 1 to sockUser.Ubound + 1
** Also if you just had For Attempt = 0 to sockUser.UBound the code would not get anywhere, as it will just keep trying to requestID on index of 0 and would not create any new winsock objects.
This is what my code now looks like and works perfectly:
Code:
For i = 1 To sockUser.UBound + 1
If VarType(sockUser(i)) = vbObject Then
Load sockUser(i)
sockUser(i).Accept requestID
Exit Sub
ElseIf sockUser(i).State <> sckConnected Then
sockUser(i).Accept requestID
Exit Sub
End If
Next i
** Take note that VarType() = vbObject is the same as VarType "is not the same as" vbObject. That's really confusing :S