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

A

Arjun

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
 
M

MRAB

Arjun said:
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()
...
 
C

Cameron Simpson

| 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 <[email protected]> DoD#743
http://www.cskk.ezoshosting.com/cs/

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top