[Gambas-user] Server socket problems (episode II)

Benoît Minisini gambas at ...1...
Sun Jun 7 03:14:33 CEST 2009


Hi,

There is a design problem in the networking component (and in Gambas streams 
generally). You cannot send data on demand. Annoying if you want to write a 
file server for example...

So I'm trying to solve that in Gambas 3 - I'm afraid I won't be able to 
backport it to Gambas 2...

I added a "Write" event to the Socket class. This event is raised after you 
have wrote something on the Socket, *and* when writing is possible again.

During the event handler of the "Write" event, you must write the data you 
want to sent in small pieces. If you write too much data during one want, you 
may block!

The "Write" event will be raised once, unless you actually write something 
during its event handler. Then it will be raised again.

A better solution is setting the Blocking property of the Socket to False, and 
then writing inside the Write event handler until an error is raised. 

If this error is actually the write() system call telling that the internal 
buffer is full, then the Write event will be raised later again. Otherwise 
this a true error and the socket is closed.

Only the Socket class is fixed, but I'd like to find a solution for every 
stream. I'm not sure I will, because File, Process and Socket are very 
different beasts.

Anyway this is better than nothing at the moment!

So here is a little example of how the ServerSocket example was modified:

-------------------------------------------------------------------------

Public Sub Server_Connection(Host As String)

  Dim Obj As Socket

  Obj = Server.Accept()
  Obj.Blocking = False
  ...
  
End

Public Sub Socket_Read()

  Dim sBuf As String

  ' Read the request
  Read #Last, sBuf, Lof(Last)
  ' Use the new Socket Tag property to register what we already sent
  Last.Tag = [0, sBuf]
  ' Call the write handler by hand to start the writing
  Socket_Write
    
End

Public Sub Socket_Write()

  Dim hSocket As Socket = Last
  Dim iInd As Integer
  
  ' If we write nothing, the Write event won't be raise again
  If IsNull(hSocket.Tag) Then Return
  
  iInd = hSocket.Tag[0]
  
  ' Write 1000 lines of text
  Do
    Inc iInd
    If iInd > 1000 Then
      hSocket.Tag = Null
      Return
    Endif
    
    Try Print #hSocket, iInd; ":";; hSocket.Tag[1]; Space$(512)

    ' If there is an error, we break
    ' If the error is actually a write buffer full, do not worry, the
    ' Write event will be raised again

    If Error Then Break

  Loop
  
  hSocket.Tag[0] = iInd

End

-------------------------------------------------------------------------

I hope the way of using that new feature is clear!

Regards,

-- 
Benoît




More information about the User mailing list