• Welcome to Valhalla Legends Archive.
 

Handling multiple sockets flawlessly?

Started by vector, October 27, 2008, 10:42 PM

Previous topic - Next topic

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)

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.

Barabajagal

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


Just make sure to close the socket when disconnected.

vector

Thanks Andy. I wish IsObject() would return False if the particular array element wasn't loaded, but it returns true....

Barabajagal

Object arrays automatically load all the elements... I think?

Ringo

Quote from: vector on October 29, 2008, 05:13 PM
I wish IsObject() would return False if the particular array element wasn't loaded, but it returns true....
Theres probly a few ways around that, but iirc, this will do the job:
IsLoaded = (VarType(Control(X))=vblong)

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...

l2k-Shadow


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


enjoy
Quote from: replaced on November 04, 2006, 11:54 AM
I dunno wat it means, someone tell me whats ix86 and pmac?
Can someone send me a working bot source (with bnls support) to my email?  Then help me copy and paste it to my bot? ;D
Já jsem byl určenej abych tady žil,
Dával si ovar, křen a k tomu pivo pil.
Tam by ses povídaj jak prase v žitě měl,
Já nechci před nikym sednout si na prdel.

Já nejsem z USA, já nejsem z USA, já vážně nejsem z USA... a snad se proto na mě nezloběj.

vector

Interesting.

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


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


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.



Quite strange.

Do you know anything about this?

Barabajagal

Let's see your close error. And next time, run it from the IDE so you find out where the error is...

Ringo

#10
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:

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




In the modClient.bas 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



in the modWinsock.bas 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



and in the clsClient.cls 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


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.

vector

In my sckRecv_Close() sub, I have a feeling that this piece of code:


  If Index = sckRecv.Count Then Unload sckRecv(Index)


Was for some reason causing the program to re-call the Close() sub, then it happens again, and again.

Barabajagal

...Why are you unloading the socket entirely like that? Are these actual Winsock objects?

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?

Barabajagal

I don't think Winsock likes dynamic arrays like that...