net-receive and waiting

Started by Grundle, May 02, 2005, 11:18:59 AM

Previous topic - Next topic

Grundle

I am currently writing an application that does substantial communication with a third party remote server using TCP.  I run into a problem when I have authenticated the connection and begin passing information between the client and the server.  I am having a problem determining exactly when the remote server has finished sending all of its data, and is ready to receive another command.



At first I tried

(set 'contents "")
(while (net-receive socket 'buf 1024)
    (set 'contents (string contents buf))
)


Unfortunately when the net-receive reaches the end of the data it will "hang" and is basically listening until the server sends it more info (which it won't).



I tried a second test as follows



(set 'contents "")
(while (net-receive socket 'buf 1024)
    (print "peek: " (net-peek socket) "n")
    (set 'contents (string contents buf))
)


I did this because I wanted to see if net-peek would indicate whether or not there was information waiting to be taken off the socket.  In many cases it returns the value "0" even though there is information.  The only instance where a value was returned is when an initial (net-receive .... 1024) buffer size is exceeded.  



I am, then, a little confused on how to determine whether or not my socket has received information from the server.  My final idea, if this is truly the case, would be to implement a "timeout" for the listener.  If it exceeds a certain time then it is in an endless wait and I can "break" the listen and go back to executing.  If this is indeed the approach I need to take can anyone enlighten me on how to implement this sort of timer construct?



Thanks,



-Keatts

Lutz

#1
Let the server close the connection after everything ii sent. This way net-receive will return nil on the client side and the loop will exit.



Lutz

Grundle

#2
That is the source of my problem.  Since it is a 3rd party server, I have no control over dropping the connection or really any server functions, furthermore since authentication is first required dropping the connection would require going back through an authentication process before reaching the same state.



Any ideas?



Thanks,



   Keatts

Lutz

#3
>>>

That is the source of my problem. Since it is a 3rd party server, I have no control over dropping the connection or really any server functions

>>>



here is a longer answer, I realize the first part isn't of interest for you, because the connection must stay open, so skip to (2)



(1) Everything depends on the mode of communications with the sever. The easiest is a 'transaction mode' where the server closes the connection after answering and sending out all information. In that case you can to the following on the client side:



(set 'content "")

(while (net-receive socket 'buff 1024)

   (write-buffer content buff))



when the sender closes the connection, the 'while' loop automatically exits. The example assumes that the server will do several sends and the client doesn't know how many.



(2) When the connection is left open you could use 'net-select' and a timeout:



(set 'content)

(while (net-select socket "r" 100000)   ; wait maximum 100 milli seconds

   (net-receive socket 'buff 1024)

   (write-buffer content buff))



In this case communications would end as soon as more than a 100 milli seconds passed after starting to receive or after the last buffer received.



In both examples a special syntax of 'write-buffer' is used to append a string in place, this is much faster than using string append:



;; the wrong slow way

(set 'content (append content buff))



;; the right and fast way

(write-buffer content buff)



Note that 'content' has to be initialized with an empty string first, so 'write-buffer' knows it has to do an in-place string append.



Last not least you could implement some kind of protocol, between server and client, letting the client know in advance how many bytes there will be transferred.



'net-peek' does not seem the right choice for what you are doing, but when you use it, you should use it before the 'net-receive' to check is bytes are ready to read, not after. In open connection communications 'net-peek' may be ambiguous, because you don't know if the sender really finished or if there are just no bytes ready at the moment you do then 'net-peek'. Of course you could use 'net-peek' together with a timeout, but 'net-select' gives you both things together.

   

Lutz

statik

#4
Yeah, I'd run a timer that was started after data was recieved. Perhaps you could work it so that each time data is sent, the timeout (timer) would be reset.
-statik

Grundle

#5
It turns out that the system is dependent on sending messages before a message can be received.  The most appropriate way to handle this was to write a receiving function that can be forked off of the main process and yet continue to send messages between the parent and child process.  



This way the parent process can continue to send commands without having to eternally wait for a response from the server.

newdep

#6
Hello Grundle,



A net-select can be used also, thought your stuck in a loop then ;-)

Still its fast enough and async..



If the remote server sends data first after your client connects the

net-select "r" can be used first and then the net-select "w"..



Is the server an known application?

Then I could build you an example perhpas..



Regards, Norman.
-- (define? (Cornflakes))