Page 1 of 1

ReceiveNetworkData(....[, BytesToReceive])

Posted: Wed Dec 16, 2009 6:33 am
by Joakim Christiansen
ReceiveNetworkData(Connection, *Buffer, BufferLength, [, Timeout [, BytesToReceive]])

Where if BytesToReceive is set it should continue waiting for data and put it in the buffer until BytesToReceive is met. And for this we also need a timeout so it wont hang if the server doesn't send us all we want. The timeout could default to 1000ms.

And if BytesToReceive isn't set then allow one to set the timeout anyway, would be handy!

For me personally I can write this function myself, but I think it would be very handy to have for working with servers. More newbie friendly! (and PB wouldn't hang anymore if there is no data to be received; it would just reach the timeout).

Re: ReceiveNetworkData(....[, BytesToReceive])

Posted: Wed Dec 16, 2009 10:54 am
by Foz
Forgive my misunderstanding, but how would you know how much you will be receiving before you receive it?

Re: ReceiveNetworkData(....[, BytesToReceive])

Posted: Wed Dec 16, 2009 11:51 am
by Joakim Christiansen
Foz wrote:Forgive my misunderstanding, but how would you know how much you will be receiving before you receive it?
Sometimes you do. Lets say a server runs a certain protocol and I send it a command and I KNOW that whatever data it replies to that command must be 128 bytes long (for example). But some servers choose to split that data up in several packets, then it makes sense to me to have a command which waits until it got it all.

In fact, these small changes to the receive function would make PureBasic very powerful for network programming! Powerful because of how simple it could interact with servers!

Right now we have to manually check each time before using ReceiveNetworkData that there actually is data to be received, if not the program will hang forever if there was no data (which is silly). So the timeout part is also important in my opinion.

I made it myself now (to be used in clients):

Client:

Code: Select all

EnableExplicit

Procedure.l clientReceiveData(serverID,*buffer,bufferSize,timeout=1000,bytesToReceive=0)
  ;Will wait until received bytesToReceive or it times out.
  ;If bytesToReceive = 0 it will wait until the first packet is received or timeout.
  ;If return value is less than bytesToReceive it means that was all it received before timeout.
  ;If it receives more than bytesToReceive it will return the number of bytes received.
  Protected dataLength, totalData, time
  If bytesToReceive > bufferSize
    totalData = -1 ;return error
  Else
    Repeat
      Delay(10): time + 10
      If NetworkClientEvent(serverID) = #PB_NetworkEvent_Data
        dataLength = ReceiveNetworkData(serverId,*buffer+totalData,bufferSize-totalData)
        If dataLength > -1
          totalData + dataLength
          time = 0 ;reset timeout each time we receive data
        EndIf
      EndIf
    Until time >= timeout Or (bytesToReceive=0 And totalData>0) Or (bytesToReceive>0 And totalData>=bytesToReceive)
  EndIf
  ProcedureReturn totalData
EndProcedure

InitNetwork()

Define serverId, *buffer, bufferSize = 1000
serverId = OpenNetworkConnection("localhost",1000)
If serverId
  *buffer = AllocateMemory(bufferSize)
  Debug clientReceiveData(serverId,*buffer,bufferSize,1000,100)
Else
  Debug "error"
EndIf
Server (to test with):

Code: Select all

EnableExplicit
Define *buffer = AllocateMemory(10000)
InitNetwork()
If CreateNetworkServer(0,1000)
  Repeat
    Select NetworkServerEvent()
      Case #PB_NetworkEvent_Connect
        SendNetworkData(EventClient(),*buffer,10)
        Delay(100)
        SendNetworkData(EventClient(),*buffer,83)
        Delay(200)
        SendNetworkData(EventClient(),*buffer,7)
        Delay(900)
        SendNetworkData(EventClient(),*buffer,6000)
    EndSelect
  ForEver
Else
  Debug "error"
EndIf
But still it would be best if this was handled by the PureBasic function I think, because sometimes this might not cooperate with your code, especially on the server side using "NetworkServerEvent" in the receive code might cause troubles.

Re: ReceiveNetworkData(....[, BytesToReceive])

Posted: Fri Dec 18, 2009 4:23 am
by Tranquil
You can adjust the BufferLength value to receive only a specific amount of data. For me there is not need for another parameter like BytesToReceive.