This is definitely the first time I ask about this topic.
Not the second time, either. I guess I'm just dumb enough
to not be able to get it all working even after reading
many replies to my earlier questions :)

May problem again, is that I have a port forwarder type of
application. Local clients send to my server, and the server
forward the traffic to remote servers. Because the local client
can send real fast, the data will be cached in twsocket's internal
send buffer. Sometimes, it reaches a few hundred MBytes, which is
not good. My solution to this is to pause local client traffic if
the BufferedByteCount of remote socket is above 8192 bytes.
Here is the code:

procedure TComm.WSocketServerClientDataAvailable(Sender: TObject; Error: Word);
begin
      ...
      len := Receive(@DataRcv, 65536);
      ...
      if TransportSocket.BufferedByteCount > 8192 then
      begin
        Log('Client paused ID=' + IntToStr(Id) + ' BufferedByteCount=' + 
IntToStr(TransportSocket.BufferedByteCount));
        TClientSocket(Sender).ComponentOptions := ComponentOptions + 
[wsoNoReceiveLoop];
        TClientSocket(Sender).Pause;
        exit;
      end;
      ...
end;

However, the client socket does not seem to pause, as I'm seeing
tons of these entries in my log window (paused but not really paused):

  Client paused ID=7 BufferedByteCount=22878
  Client paused ID=7 BufferedByteCount=22878
  Client paused ID=7 BufferedByteCount=22878
  Client paused ID=7 BufferedByteCount=22878
  Client paused ID=7 BufferedByteCount=22878
  
I'm also logging Resume() calls but according to the log, Resume()
were not called when the Pause() calls happened.

Not wanting to waste others' time replying to me again, I dig the
old emails on this matter and read them again but couldn't find what
I'm doing wrong. Below are some excerpts from past emails. It could
be compiled in one of the wiki pages.


-- 
Best regards,
Jack



[From Francios]

It (Pause) suppress async notification. So you don't receive events anymore
but I/O continue as much as winsock can, for example filling his receive buffer.

You can't ignore OnDataavailable event ! If you don't call Receive from
OnDataAvailable event, the event will be triggered again and again until
you read the data. You'll enter an infinite loop. Calling Pause will stop
OnDataAvailable from being triggered, ...

Pause only affect winsock notification. It stops notifications from winsock
but if data is already in, you have to read it.
Try the option wsoNoReceiveLoop, it may help to stop delivering of already 
received data. If you use the option and pause the socket, you will not be 
notified of any data already received and waiting in the buffer. So when you 
resume, you should probably call Receive once to check for remaining data.

wsoNoReceiveLoop tell the component to not loop until the message queue has
no more FD_READ messages. When a loop is done (default) the component 
receive data as fast as possible. This maybe result is heavy load on the 
computer when the network is very fast compared to the CPU speed.

It (wsoNoReceiveLoop) shouldn't have any impact on the high level protocol,
except speed.

Speaking about your application: are you sure you still receive data ? From
OnDataAvailable event handler, you must receive everything or you enter an 
infinite loop when wsoNoReceiveLoop is not activated and if activated but 
you don't call Receive, then you don't get any notification before you cxall 
Receive.

If you call Pause, obviously you are no more notifyed when data comes in. 
This will fill the receive buffer until full and at that time the peer will 
recive the zero window message. Before timeout you must call resume and 
probably Receive as well to restart the receiving process.


[From Wilfried]

- Pause will stop notification from winsock. If there is already data
  received then OnDataAvailable will keep on firing for a while until
  you have received.

  After that winsock buffer will fill but no notification. When winsock
  buffer is full then sender will stop sending data.

- Resume will turn notification back on, so filled up receive buffer
  from winsock will fire onDataAvailable again.

- if you set wosNoReceivedLoop and you do NOT receive in OnDataAvaliable
  then it will also not fire again until you call receive. This means
  that you have to call Receive outside the OnDataAvailable to turn it
  on again.

- A combination of both should be working also. You call pause, and when
  you are in paused state you dont want to receive even if there is
  already somethign to receive as you explained in a previous mail. Then
  you do the wsoNoReceivLop;

  I "think" if combine both, and you call Resume that OnDataAvailable
  will fire again without calling Receive outside of it. You can try it
  easely of course. Pleas let us know, this is valuable information.

-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to