Page 1 of 1

Network: Better error handling

Posted: Sat Sep 05, 2015 2:11 am
by Sicro
SendNetworkString() should have a parameter to set the time-out.
Without this parameter, the server can block the client for a long time, when the server doesn't handle the data.

Better: More error handling

Re: SendNetworkString(): Timeout

Posted: Sat Sep 05, 2015 8:48 pm
by RichAlgeni
I don't believe your assertion is correct. If it were, the entire internet would ground to a halt waiting on packet sends to complete.

Post the code you are having an issue with, and we'll take a look at it.

Re: SendNetworkString(): Timeout

Posted: Sun Sep 06, 2015 1:38 am
by Sicro
Other programs are be stopping sending more data, after a while, when the server isn't fast enough.
I think, SendNetworkString does it too, but to late - or it's a endless loop.
RichAlgeni wrote:Post the code you are having an issue with, and we'll take a look at it.
Example code to have this problem:

Server

Code: Select all

If Not InitNetwork() Or Not CreateNetworkServer(0, 6500)
  Debug "Network error"
  End
EndIf

Repeat
  Event = NetworkServerEvent()
  Select Event
    Case #PB_NetworkEvent_Connect
      Debug "Client has connected."
    Case #PB_NetworkEvent_Data
      ; Client is sending data. The server will block the work of the client by he doesn't handle the incoming data.
    Default
      Delay(10)
  EndSelect
ForEver
Client

Code: Select all

If Not InitNetwork()
  Debug "Network error"
  End
EndIf

Connection = OpenNetworkConnection("localhost", 6500)
If Not Connection
  Debug "Network error"
  End
EndIf

Debug "Begins sending data."
; Now we send a lot of strings, so that the internal buffer is full and he can no longer accept data.
For i = 1 To 200000
  SendNetworkString(Connection, "This is a test string.")
Next
Debug "This will be never seen, because SendNetworkString blocks until the transfer is completed."

Re: SendNetworkString(): Timeout

Posted: Sun Sep 06, 2015 10:01 am
by heartbone
Sicro wrote:SendNetworkString() should have a parameter to set the time-out.
Without this parameter, the server can block the client for a long time, when the server doesn't handle the data.
Sicro wrote:Other programs are be stopping sending more data, after a while, when the server isn't fast enough.
I think, SendNetworkString does it too, but to late - or it's a endless loop.
RichAlgeni wrote:Post the code you are having an issue with, and we'll take a look at it.
Example code to have this problem:
{snip}

Code: Select all

Debug "Begins sending data."
; Now we send a lot of strings, so that the internal buffer is full and he can no longer accept data.
For i = 1 To 200000
  SendNetworkString(Connection, "This is a test string.")
Next
Debug "This will be never seen, because SendNetworkString blocks until the transfer is completed."
Although I comprehend your request for the enhancement,
calling the procedure SendNetworkString() 200,000 times consecutively without any intervening code to produce the conditions necessary to show the problem seems a bit extreme.
That code does not seem represent in any sense of the word, what could be considered a normal problem.
If you could produce the problem after less than 100 such calls, then it might enter the realm of a bug in a somewhat practical scenario.

BTW Sicro, the SendNetworkString() function is buggy the last time I looked at it, it should be used very carefully.
As long as your strings are less than 256 characters then you can directly substitute this code and then see what happens.

Code: Select all

Procedure SNETSTRING(ID,STRING$)
; REPLACES SendNetworkString(ID,STRING$,#PB_UTF8)
   *SBUFFER= AllocateMemory(256)
   PokeS(*SBUFFER,STRING$,Len(STRING$)+1,#PB_UTF8)
   SendNetworkData(ID,*SBUFFER,Len(STRING$)+1)
   FreeMemory(*SBUFFER)
EndProcedure

Re: SendNetworkString(): Timeout

Posted: Sun Sep 06, 2015 10:38 am
by HeX0R
The server will send a wsaewouldblock to the client, if he gets flooded with data and can't handle it fast enough.
Then it's on the client to wait until he gets a clear message from the server.

Unfortunately the error handling of the network library is almost not existant, without API you have no chance to distinguish between all of the possible reasons SendNetworkData failed.

We would need better error handling instead of a timeout parameter.

I'm quite sure I requested this years ago, but can't find it anymore.

Re: SendNetworkString(): Timeout

Posted: Sun Sep 06, 2015 1:59 pm
by Sicro
heartbone wrote:calling the procedure SendNetworkString() 200,000 times consecutively without any intervening code to produce the conditions necessary to show the problem seems a bit extreme.
That code does not seem represent in any sense of the word, what could be considered a normal problem.
If you could produce the problem after less than 100 such calls, then it might enter the realm of a bug in a somewhat practical scenario.

Code: Select all

If Not InitNetwork()
  Debug "Network error"
  End
EndIf

Connection = OpenNetworkConnection("localhost", 6500)
If Not Connection
  Debug "Network error"
  End
EndIf

Debug "Begins sending data."

For i = 1 To 200000
  String.s + "This is a test string."
Next
SendNetworkString(Connection, String)

Debug "This will be never seen, because SendNetworkString blocks until the transfer is completed."
Another way:
1. Send data with SendNetworkData() to get the internal buffer nearly full.
2. Send a string with SendNetworkString() to overfill the buffer
3. Client stops working

The problem is not only with SendNetworkString(), but also at SendNetworkData().
When the internal buffer is full, also blocks SendNetworkData().

Code: Select all

If Not InitNetwork()
  Debug "Network error"
  End
EndIf

Connection = OpenNetworkConnection("localhost", 6500)
If Not Connection
  Debug "Network error"
  End
EndIf

Debug "Begins sending data."

*FileData = AllocateMemory(1024*1024*10) ; 10 MiB fails, 1 MiB ok
DataSize = MemorySize(*FileData)
Offset = 0
Repeat
  SentDataSize = SendNetworkData(Connection, *FileData+Offset, DataSize-Offset)
  If SentDataSize > 0
    Offset + SentDataSize
  EndIf
Until Offset = DataSize

Debug "This will be never seen, because SendNetworkData blocks until the transfer is completed." 
@HeX0R: Yes, more error handling will be better. I have changed the title of the topic.

Re: Network: Better error handling

Posted: Sun Sep 06, 2015 6:49 pm
by RichAlgeni
One other tip I would suggest it to trigger your reads from the server side with NetworkServerEvent() on #PB_NetworkEvent_Connect, and not #PB_NetworkEvent_Data IF you will be using threads to service the sockets.

I have found that multiple instances of #PB_NetworkEvent_Data per connection can be triggered if your loop is tight enough, but only one instance per connection of #PB_NetworkEvent_Connect will be triggered.'

Also, never close a server socket, allow this system to do so. But always close client sockets!