[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

How to end TCP socket data while using readline()?

Arjun

2/26/2010 6:39:00 PM

Hi, I have a small script that runs a TCP server. A client connects to
this server and transmits a stored file line-by-line, and then waits
for a confirmation "done". However, when I run them the first loop
never really ends -- as the TCP server keeps expecting more data. I am
using a file-like-object, and so somehow I have to communicate to the
server that it is the end-of-file.

here is some server code
<snip>
sock1.bind(('', port))
print "Listening at port: ", port
sock1.listen(1) # listening socket
(conn, addr) = sock1.accept() # connected socket
print 'Client (localhost) port: ', addr[1]

cf = conn.makefile('r',0) # file like obj for socket

lf = open('ccs.txt','w')
for line in cf:
lf.write(line)
lf.flush()
sys.stdout.write(line)
print len(line)

lf.close() (*here*)
cf.close()
cf = conn.makefile('w',0)
print len(line)
print 'sendin'
stat = 'done'
cf.write(stat)
print stat
print 'sent'
cf.close()
print 'script done & connection closed'
</snip>

The client is sending the lines through this code:
<snip>
s.connect((host,port))
sfp = open("dcs.txt")
# script = sfp.readlines()
stat = 'still'
cf = s.makefile('w',0)
for line in sfp.readlines():
cf.write(line)
print len(line)
print 'close'
cf.flush()
cf.close()
sfp.close()

cf = s.makefile('r',0)
print stat, 'waiting'
stat = cf.readline()
print stat, 'waiting' # this should become "done waiting"
cf.close()
s.close()
</snip>

So what I am wondering is:

1. Using a file-like object means that the socket becomes uni-
directional, until the mode of the file object is changed from 'r' to
'w' (or vice versa). This seems inefficient, and rather unPythonesque.
Can somebody tell me if there is a more elegant way of receiving all
the lines from the client, and then sending a "done" message to the
client?

2. Where I have marked (*here*) in the server code, is where the
execution seems to stay waiting... apparently for more input from the
client. But then when I force-terminate the client script, the
execution continues on the server-side!! So then it sends the "done"
status to a (already dead) client, and then exits. How do I get the
server to know when the EOF has been reached while using FLOs?

Input on this will be much appreciated, because the documentation for
readlines() didn't help me with this.

Cheers,
A
2 Answers

MRAB

2/26/2010 7:46:00 PM

0

Arjun Chennu wrote:
> No need to flush because you're writing to a file and it'll be flushed
>
> anyway when you close it.
>
>
> True. I had introduced those flush lines while I was trying to
> troubleshoot this annoying situation. :-)
>
> You've closed the file view, but the underlying socket is still open.
>
>
> The server will see EOF only when the socket is closed by the client,
> and closing the file view doesn't close the socket itself.
>
>
> That's what I intended to do. Keep the socket open, but close the file
> object so that the direction of transfer can be reversed and a "done"
> message can be sent to the client.
>
> TCP is meant to facilitate two-directional transfer innit? So how do I
> do that while using file objects? If i have to close the socket to do
> that, it seems a bit wasteful in terms of network 'transactions'
>
> Thanks for your reply. I've already confirmed that closing the socket
> does indeed move the program ahead --- but I'd like to now make
> two-directional comm. possible.
>
Here's a trick borrowed from the POP3 format (used for email).

Server code:
...
cf = conn.makefile('r', 0) # file like obj for socket
lf = open('ccs.txt', 'w')
for line in cf:
if line == '.end\n':
break
if line.startswith('..'):
line = line[1 : ]
lf.write(line)
sys.stdout.write(line)
print len(line)
lf.close()
cf.close()
...


Client code:
...
cf = s.makefile('w', 0)
for line in sfp.readlines():
if line.startswith('.'):
cf.write('.')
cf.write(line)
print len(line)
cr.write('.end\n')
print 'close'
cf.close()
...

Cameron Simpson

2/27/2010 4:11:00 AM

0

On 26Feb2010 10:39, Arjun <arjun.chennu@gmail.com> wrote:
| Hi, I have a small script that runs a TCP server. A client connects to
| this server and transmits a stored file line-by-line, and then waits
| for a confirmation "done". However, when I run them the first loop
| never really ends -- as the TCP server keeps expecting more data. I am
| using a file-like-object, and so somehow I have to communicate to the
| server that it is the end-of-file.
|
| here is some server code
| <snip>
| sock1.bind(('', port))
| print "Listening at port: ", port
| sock1.listen(1) # listening socket
| (conn, addr) = sock1.accept() # connected socket
| print 'Client (localhost) port: ', addr[1]
|
| cf = conn.makefile('r',0) # file like obj for socket
[...]
| print 'close'
| cf.flush()
| cf.close()
| sfp.close()
[...]

Too many files. It's not that hard! Or shouldn't be.

| So what I am wondering is:
|
| 1. Using a file-like object means that the socket becomes uni-
| directional, until the mode of the file object is changed from 'r' to
| 'w' (or vice versa). This seems inefficient, and rather unPythonesque.
| Can somebody tell me if there is a more elegant way of receiving all
| the lines from the client, and then sending a "done" message to the
| client?

Get the socket. It is a file descriptor (or in may be a python "socket"
object with a file descriptor inside).

Open _two_ "file" objects on it using
from_file = os.fdopen(fd_of_socket, "r")
to_file = os.fdopen(fd_of_socket, "w").

Use the same:
print >>to_file, 'close'
to_file.flush()
method as you're using already.
Read from to_file as needed.

The same scheme should work in both server and client:

Don't look for EOF, watch the input line flow.

You might need to use readline() instead of the file-by-line iteration stuff,
which I seem to recall has some sort of problem handing out the "latest"
line.

Cheers,
--
Cameron Simpson <cs@zip.com.au> DoD#743
http://www.cskk.ezoshosti...

It's better, when you're riding with someone you don't know so well, to stick
to the inside line - it's easier to avoid the bits...
- Barry Sheene