Page 1 of 2

Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 3:36 pm
by srod
Hi,

I am a little puzzled by an aspect of ReceiveNetworkData(). When used by a client without a client event loop (i.e. without using NetworkClientEvent() etc.) then this function seems to block execution in the case that the server has not sent any data and has not closed the connection.

I am puzzled because I know that PB uses non-blocking sockets.

Is this behaviour to be expected and should I thus definitely use a client event loop? The reason I ask is because, for the client, I would prefer not to use a client event loop.

Test code...

Server.

Code: Select all

If InitNetwork() = 0
  MessageRequester("Error", "Can't initialize the network !", 0)
  End
EndIf

Port = 6509

If CreateNetworkServer(0, Port)
  MessageRequester("PureBasic - Server", "Server created (Port "+Str(Port)+").", 0)
  Repeat
    Delay(1)
    SEvent = NetworkServerEvent()
    If SEvent
      ClientID = EventClient()
      Select SEvent
        Case #PB_NetworkEvent_Connect
          Debug "A new client has connected!"

        Case #PB_NetworkEvent_Disconnect
          Debug "Client has disconnected!"
          Quit = 1
    
      EndSelect
    EndIf
    
  Until Quit = 1 
  
  CloseNetworkServer(0)
Else
  MessageRequester("Error", "Can't create the server (port in use ?).", 0)
EndIf

Client.

Code: Select all

If InitNetwork() = 0
  MessageRequester("Error", "Can't initialize the network !", 0)
Else
  Port = 6509
  *buffer = AllocateMemory(1000)
  ConnectionID = OpenNetworkConnection("localhost", Port)
  If ConnectionID
    Debug "About to call ReceiveNetworkData() ......"
    ReceiveNetworkData(ConnectionID, *Buffer, 40)
    Debug "ReceiveNetworkData() has returned!"
    CloseNetworkConnection(ConnectionID)
  Else
    MessageRequester("PureBasic - Client", "Can't find the server (Is it launched ?).", 0)
  EndIf
EndIf
Thanks.

Re: Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 5:45 pm
by Rook Zimbabwe
Srod
This is the entire code of my SQL server for my POS

Code: Select all

code removed per srods request...
If it helps... run amuck with it! (A nod in the creds would be nice to all those who utilize it!)
{{removed code}}

Re: Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 6:06 pm
by srod
Well that is some nice looking code Rook... but it does not belong in this thread. I did not ask for any code and there is nothing in there which comes close to addressing my question.

I would appreciate it if you would remove the code and place it in a separate thread as it simply gets in the way here. I am sure that there are indeed people who can make good use of what looks to be some valuable server/ODBC code, but at this time I am interested only in those who might be able to shed some light on my client question and indeed have the time to do so.

No offence intended Rook.

Re: Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 6:08 pm
by Fred
You need to call ReadNetworkData() only if you got an event which tell you than some data awaits in the pipe (or the read will block).

Re: Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 6:18 pm
by srod
Fred wrote:You need to call ReadNetworkData() only if you got an event which tell you than some data awaits in the pipe (or the read will block).
Righty-ho. That answers that one - though I guess it was kind of obvious considering that the read was indeed blocking! :) Is this done at the api level Fred? The reason I ask is that well, PB uses non-blocking sockets which is why I imagined that ReadNetworkData() would never block, even if there was no data to read.

Thanks Fred.

Re: Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 7:16 pm
by idle
maybe just bung the client event loop in a thread with an invisible window and use a callback.

Re: Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 8:12 pm
by Rook Zimbabwe
Actully srod if you had a glance at it I use that in both the server and client side... in the events...

I do encode the string of data that gets recieved so the program or server knows what to do with it.

Re: Puzzled by ReceiveNetworkData().

Posted: Tue Feb 23, 2010 9:42 pm
by srod
idle wrote:maybe just bung the client event loop in a thread with an invisible window and use a callback.
This is a cross-platform server! :wink: I can work with a client event loop okay, not a problem, even if I had originally attempted to avoid it.

Rook wrote:I do encode the string of data that gets recieved so the program or server knows what to do with it.

Posted: Tue Feb 23, 2010 19:12
Already have that covered. Your code doesn't address the blocking nature of ReceiveNetworkData() under the circumstances described above which is why, with no disrespect intended, the code didn't belong here. :wink: To be honest Rook, that code of yours deserves it's own thread anyhow as it looks very good indeed.

Re: Puzzled by ReceiveNetworkData().

Posted: Wed Feb 24, 2010 12:38 am
by Rook Zimbabwe
Thanks SRod... I appreciate the nice compliment :D

I was also attempting to show where I handled the recieve events... (and as a side HOW) because i didn't want extraneous info pings to the server (I did change them in the examples FYI!) 8)

I had not cinsidered blocking though... hmmm... I was also considering rewriting the server using MAP when I understad it better...

(That was a int for you to write another excellent tutorial!) :wink:

Re: Puzzled by ReceiveNetworkData().

Posted: Wed Feb 24, 2010 1:39 am
by idle
srod wrote:
idle wrote:maybe just bung the client event loop in a thread with an invisible window and use a callback.
This is a cross-platform server! :wink: I can work with a client event loop okay, not a problem, even if I had originally attempted to avoid it.


What's the issue or problems of bunging it into a thread on other OS's?
I don't know as I haven't tried! I don't think a window is needed at all

Re: Puzzled by ReceiveNetworkData().

Posted: Wed Feb 24, 2010 10:27 am
by Foz
srod wrote:
idle wrote:maybe just bung the client event loop in a thread with an invisible window and use a callback.
This is a cross-platform server! :wink: I can work with a client event loop okay, not a problem, even if I had originally attempted to avoid it.
As a big cross platform fan (develop in Linux, execute in Windows) I have posted something like this:
http://www.purebasic.fr/english/viewtop ... 22#p222722

You will notice that in the example given, I've commented out the CreateThread() on the server - that was part of my test to see now many clients it can handle without threading vs with threading.

Re: Puzzled by ReceiveNetworkData().

Posted: Wed Feb 24, 2010 11:02 am
by srod
How did it turn out with the threading? My server is multi-threaded which, whilst it is still early days, is working well. Truth is that I am not aiming for a massive number of concurrent client connections and so I am 'reasonably' confident that having one server thread per client should work okay for me.

Re: Puzzled by ReceiveNetworkData().

Posted: Wed Feb 24, 2010 11:25 am
by Foz
I think I decided that running single threaded was more than adequate - I would be working with data sizes of upto 1mb, but overall on average about 2kb, which negated the need for threading. If I was going to be working with large data transfers, then threading would come into it's own.

Re: Puzzled by ReceiveNetworkData().

Posted: Wed Feb 24, 2010 11:37 am
by srod
Okay, blocking problem solved.

Here was the problem in a nutshell.

Basically, when a client connects to my server, the server decides whether to allow the connection. E.g. has the max number of connections been reached? Can the server allocate the resources required to service the client? Can it start a new thread to service the client etc? In cases where it decides to refuse the connection, it sends the client an error code and then immediately terminates the connection server side. This is fine, except that my client was having problems receiving this notification of a connection refusal.

The problem is that I was deferring checking the return code until the client had sent an initial request to the server (which is part of the connection protocol for my library). I figured that checking the return value could wait. This puts the server in the position of having been sent data which it does not retrieve (because it is about to close the connection) and when it then sends the aforementioned error code followed by closing the connection, the client simply does not receive a #PB_NetworkEvent_Data event unless I delay the server from terminating the connection. (Hence the reason for my wishing to avoid the use of #PB_NetworkEvent_Data client-side!)

The problem is the data being sent to the server and not being retrieved. I am unsure why this should prevent the receipt of a #PB_NetworkEvent_Data event client-side without the aforementioned server delay, but the fact is that it does! :) I have now modified the client code to check for an error return immediately on being granted the connection to see if the server has terminated the connection with an error code etc. and all is well again!

Lesson painfully learned. A bit of a mine-field this networking stuff, figuring out what 'abuses' I can and cannot get away with! :)

Re: Puzzled by ReceiveNetworkData().

Posted: Wed Feb 24, 2010 11:41 am
by srod
Foz wrote:I think I decided that running single threaded was more than adequate - I would be working with data sizes of upto 1mb, but overall on average about 2kb, which negated the need for threading. If I was going to be working with large data transfers, then threading would come into it's own.
Makes sense. Mine could be dealing, not so much with large transfers, but potentially quite a lot of processing in response to certain client requests etc. which is why I have gone down the multi-threaded path.