I swear I do my best thinking in the bathroom, as it occurred to me there that I should instead create the thread to handle the new connection based upon the server event #PB_NetworkEvent_Connect instead of #PB_NetworkEvent_Data. I'm not sure how much of a difference it makes in the overall performance of a program, but I wanted to offload the work of receiving and sending network data entirely to the threads.
Here's what I ended up with, if it can help anyone out there, great! Please note that this code uses a Windows socket API to return the amount of data in the receive buffer.
Code: Select all
EnableExplicit
Procedure ProcessRequest(clientNumber)
Protected *memoryLocation
Protected length.i
Protected result.i
Protected amountRead.i
Protected attemptCount.i
Protected socketHandle.i
Protected memLength.i = 10000
Protected maxReadTrys.i = 20
Protected socketTimeout.i = 100
Protected errNumber.i = 0
PrintN("Client " + Str(clientNumber) + " connected")
socketHandle = ConnectionID(clientNumber)
*memoryLocation = AllocateMemory(10000)
Repeat
attemptCount = 0
amountRead = 0
; loop until we have received data, or our timeout has been exceeded
Repeat
result = ioctlsocket_(socketHandle, #FIONREAD, @length)
If result < 0; socket error
amountRead = result
errNumber = WSAGetLastError_()
Break
ElseIf result > 0; socket error
amountRead = result * -1
errNumber = WSAGetLastError_()
Break
ElseIf length > 0; we have data in the receive buffer
If length > memLength
length = memLength
EndIf
; loop here until we've read in all the data in the buffer
While length > 0
result = ReceiveNetworkData(clientNumber, *memoryLocation + amountRead, length)
If result > 0
amountRead = amountRead + result
length = length - result
Else
amountRead = result * -1
errNumber = WSAGetLastError_()
length = 0
EndIf
Wend
Break
Else
Delay(socketTimeout)
attemptCount = attemptCount + 1
If attemptCount > maxReadTrys; if still nothing received, just get out
Break
EndIf
EndIf
ForEver
; show what we ended up with
Select amountRead
Case 0
PrintN("Client " + Str(clientNumber) + " received nothing from socket")
Case 1 To 65535
PrintN("Client " + Str(clientNumber) + " received " + Str(amountRead) + " bytes: " + PeekS(*memoryLocation, result))
Default
PrintN("Client " + Str(clientNumber) + " received an error: " + Str(errNumber) + ", thread terminating")
EndSelect
If amountRead < 0
Break
EndIf
ForEver
FreeMemory(*memoryLocation)
EndProcedure
Define NSEvent.i
Define thisClient.i
Define keyPressed.s
Define serverNumber.i
Define portNumber.i = 8901
; initialize the network and create the server needed
InitNetwork()
serverNumber = CreateNetworkServer(#PB_Any, portNumber)
OpenConsole()
PrintN("Started Network Server on port " + Str(portNumber))
PrintN("Press Escape to exit")
PrintN("")
Repeat
NSEvent = NetworkServerEvent() ; if we receive data, it will be indicated here
Select NSEvent
Case #PB_NetworkEvent_Connect ; a socket has connected
thisClient = EventClient() ; get the event client identifier
CreateThread(@ProcessRequest(), thisClient); threaded procedure to process incoming data
Case #PB_NetworkEvent_Data ; raw data has been received
Case #PB_NetworkEvent_File ; uploading a file
Case #PB_NetworkEvent_Disconnect; a socket disconnected
Default; no server event occurred
EndSelect
Delay(20); sleep so we don't hammer the processor
keyPressed = Inkey()
Until keyPressed = #ESC$
PrintN("Escape pressed, press <enter> to terminate this process")
CloseNetworkServer(serverNumber)
Input()
End