Valhalla Legends Forums Archive | Visual Basic Programming | Handling multiple sockets flawlessly?

AuthorMessageTime
vector
I'm trying to polish my server so it can handle multiple sockets flawlessly. Say three sockets are connected.

When socket 2 leaves, I want to be able to re-use socket 2. When 1 leaves, I want to re-use 1, etc.

I keep trying so and get problems. I've been trying again and again to handle sockets perfectly.

Please note that I'm using two sockets. A listening socket, and a control array.

Can you post an example of the proper way of handling sockets? (the Winsock_ConnectionRequest Sub is all I need)
October 28, 2008, 3:42 AM
Yegg
Couldn't they all simply operate on their own thread?  Store them in an array as you are already doing. If they are all on their own thread, you can have a function running within each thread that does whatever task whenever the socket loses its connection. Should be pretty simple.
October 28, 2008, 4:47 AM
Barabajagal
[code]Dim I As Integer
 For I = 0 To 99
   If Winsock(I).State = 0 Then
     Winsock(I).Accept requestID
     Exit For
   End If
 Next I[/code]

Just make sure to close the socket when disconnected.
October 28, 2008, 4:56 AM
vector
Thanks Andy. I wish IsObject() would return False if the particular array element wasn't loaded, but it returns true....
October 29, 2008, 10:13 PM
Barabajagal
Object arrays automatically load all the elements... I think?
October 29, 2008, 11:40 PM
Ringo
[quote author=vector link=topic=17697.msg180164#msg180164 date=1225318421]
I wish IsObject() would return False if the particular array element wasn't loaded, but it returns true....
[/quote]
Theres probly a few ways around that, but iirc, this will do the job:
IsLoaded = (VarType(Control(X))=vblong)
October 29, 2008, 11:46 PM
Barabajagal
I know you can do If Not Ary() Then to detect if an array hasn't been initialized, but I don't think individual elements of arrays work like that...
October 30, 2008, 12:39 AM
l2k-Shadow
[code]
Private Sub Form_Load()
Dim i As Integer
   'Load Winsock1(1)
   For i = 0 To 1
       If IsLoaded(Winsock1(i)) Then MsgBox i & " Is Loaded!"
   Next i
End Sub

Public Function IsLoaded(ByVal W As Winsock) As Boolean
   If VarType(W) <> vbObject Then IsLoaded = True
End Function
[/code]

enjoy
October 30, 2008, 12:49 AM
vector
Interesting.

I took Andy's advice, and it looks nicely:

[code]
Private Sub sckListen_ConnectionRequest(ByVal requestID As Long)
  Dim i As Integer
 
  For i = 0 To sckRecv.Count
    If i = sckRecv.Count Then
      Load sckRecv(i)
      sckRecv(i).Accept requestID
      Exit Sub
    Else
      If sckRecv(i).State = sckClosed Then
        sckRecv(i).Accept requestID
        Exit Sub
      End If
    End If
  Next
End Sub
[/code]

But the wird thing is, when a client leaves, the sckRecv_Close() sub seems to be calling more than once, and the clients seem to be acting up.

[IMG]http://i52.photobucket.com/albums/g38/dj_dances/weird-1.jpg[/img]

Quite strange.

Do you know anything about this?
November 3, 2008, 9:07 PM
Barabajagal
Let's see your close error. And next time, run it from the IDE so you find out where the error is...
November 3, 2008, 10:02 PM
Ringo
id persionaly do somthing like this (dunno if this helps you at all)
create module called modWinsock.bas
create a module called modClient.bas
create a class called clsClient.cls

modwinsock.bas would be used to managed an array of winsocks, across the whole project.
modclient.bas would be used to manage an array of client class's
clsclient.cls would be used to manage a clients connection and what not.

then in you're form code:
[code]
Public WithEvents sckServer     As MSWinsockLib.Winsock

Private Sub Form_Load()
    Dim i       As Integer
    modWinsock.hSocketCount = -1
    modClient.hClientCount = -1
    i = modWinsock.GetFreeSocket(Me)
    Set sckServer = modWinsock.hSocket(i)
    sckServer.Close
    sckServer.Bind 2392, sckServer.LocalIP
    sckServer.Listen
End Sub

Private Sub sckServer_ConnectionRequest(ByVal requestID As Long)
    Dim i       As Integer 'socket index
    Dim i2      As Integer 'client index
    i = modWinsock.GetFreeSocket(Me)
    i2 = modClient.GetFreeClient()
    modClient.hClient(i2).sckIndex = i
    Set modClient.hClient(i2).sckRecv = modWinsock.hSocket(i)
    Call modClient.hClient(i2).Accept(requestID)
End Sub
[/code]



In the modClient.bas code:
[code]
Public hClient()            As clsClient
Public hClientInUse()       As Boolean
Public hClientCount         As Integer

Public Function GetFreeClient() As Integer
    Dim i       As Integer
    For i = 0 To hClientCount
        If (hClientInUse(i) = False) Then
            hClientInUse(i) = True
            GetFreeClient = i
            Exit Function
        End If
    Next i
    hClientCount = hClientCount + 1
    i = hClientCount
    ReDim Preserve hClientInUse(i)
    hClientInUse(i) = True
    ReDim Preserve hClient(i)
    Set hClient(i) = New clsClient
    hClient(i).clsIndex = i
    GetFreeClient = i
End Function
Public Sub ReleaseClient(ByVal i As Integer)
    If (i < 0) Or (i > hClientCount) Then Exit Sub
    Set hClient(i).sckRecv = Nothing
    Call modWinsock.ReleaseWinsock(hClient.sckIndex)
    hClient(i).sckIndex = -1
    hClientInUse(i) = False
End Sub
[/code]


in the modWinsock.bas code:
[code]
Public hSocket()        As MSWinsockLib.Winsock
Public hSocketInUse()   As Boolean
Public hSocketCount     As Integer

Public Function GetFreeSocket(ByRef F As VB.Form) As Integer
    Dim i       As Integer
    For i = 0 To hSocketCount
        If (hSocketInUse(i) = False) Then
            hSocketInUse(i) = True
            GetFreeSocket = i
            Exit Function
        End If
    Next i
    hSocketCount = hSocketCount + 1
    i = hSocketCount
    ReDim Preserve hSocketInUse(i)
    hSocketInUse(i) = True
    ReDim Preserve hSocket(i)
    Set hSocket(i) = F.Controls.Add("MSWinsock.Winsock", "Winsock" & i)
    GetFreeSocket = i
End Function
Public Sub ReleaseSocket(ByVal i As Integer)
    If (i < 0) Or (i > hSocketCount) Then Exit Sub
    If hSocketInUse(i) Then
        hSocketInUse(i) = False
        hSocket(i).Close
    End If
End Sub
[/code]


and in the clsClient.cls code:
[code]
Public WithEvents sckRecv       As MSWinsockLib.Winsock
Public clsIndex                 As Integer
Public sckIndex                 As Integer

Public Sub Accept(ByVal requestID As Integer)
    sckRecv.Close
    sckRecv.Accept requestID
End Sub



Private Sub sckRecv_Close()
    Call modClient.ReleaseClient(clsIndex)
End Sub
Private Sub sckRecv_Error(ByVal Number As Integer, _
                          Description As String, _
                          ByVal Scode As Long, _
                          ByVal Source As String, _
                          ByVal HelpFile As String, _
                          ByVal HelpContext As Long, _
                          CancelDisplay As Boolean)
    Call modClient.ReleaseClient(clsIndex)
End Sub
[/code]

That way, you can manage many types of client's/class's, all from the same winsock array.
For example, you could have a clsFTP.cls client class, that could also get an avalible socket index, from the winsock array. 1 array of winsocks, multiple uses.
But thats just me :p
Dunno if that helps you, or puts an idea in your head or not.
November 4, 2008, 5:13 AM
vector
In my sckRecv_Close() sub, I have a feeling that this piece of code:

[code]
  If Index = sckRecv.Count Then Unload sckRecv(Index)
[/code]

Was for some reason causing the program to re-call the Close() sub, then it happens again, and again.
November 4, 2008, 8:23 PM
Barabajagal
...Why are you unloading the socket entirely like that? Are these actual Winsock objects?
November 4, 2008, 8:26 PM
vector
Yes. Well, it's a control array actually. I load the socket if its last socket in the array. Should I not unload it?
November 4, 2008, 11:57 PM
Barabajagal
I don't think Winsock likes dynamic arrays like that...
November 5, 2008, 12:10 AM
vector
I feel like an idiot. On the client, when the form terminated, it would call sckSend.Close, and on the server side, when the socket quits, the close() sub was actually executing twice. I took that line from the client out, and it does just what its supposed to do normally.
November 5, 2008, 7:46 PM
TheMinistered
search pscode.com for "david Fritts" you'll find really good sample project on how to do this
November 20, 2008, 7:37 PM

Search