[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