Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python socket send EOF

Tags:

python

sockets

I have a simple file transfer socket program where one socket sends file data and another socket receives the data and writes to a file

I need to send an acknowledgment once transfer is finished from the destination to the source

Code for destination

s.accept()
f = s.makefile()
f.read(1024)

Code for source

s.connect(('localhost',6090))
f = s.makefile()
f.write('abcd') 
f.flush()

Here comes the problem, since "abcd" is not 1024 bytes, the destination will block till 1024 bytes are received
The solution would be to close() the socket, but since I need a confirmation from destination, I cannot close the socket.
How do I tell the destination to stop blocking? I was thinking of writing an EOF character I read online that "\x04" is EOF, but it doesn't work.
Also since the data could be binary I don't want to use the readline() method.

like image 502
ages04 Avatar asked Sep 24 '10 15:09

ages04


People also ask

What is socket Af_inet in Python?

AF_INET is the Internet address family for IPv4. SOCK_STREAM is the socket type for TCP, the protocol that will be used to transport messages in the network. The . bind() method is used to associate the socket with a specific network interface and port number: # echo-server.py # ... with socket.

How do you send data from client to server in socket programming in Python?

To connect to a server-socket on the local computer, use localhost as the hostname in the server address tuple. After the client-side socket has connected to the server-side socket, data can be sent to the server using the send(string [,flags]) method.

What is socket Sock_stream?

SOCK_STREAM. Provides sequenced, two-way byte streams with a transmission mechanism for stream data. This socket type transmits data on a reliable basis, in order, and with out-of-band capabilities. In the UNIX domain, the SOCK_STREAM socket type works like a pipe.


3 Answers

Design a protocol (an agreement between client and server) on how to send messages. One simple way is "the first byte is the length of the message, followed by the message". Rough example:

Client

Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import *
>>> s=socket()
>>> s.connect(('localhost',5000))
>>> f=s.makefile()
>>> f.write('\x04abcd')
>>> f.flush()

Server

Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import *
>>> s=socket()
>>> s.bind(('localhost',5000))
>>> s.listen(1)
>>> c,a=s.accept()
>>> f=c.makefile()
>>> length=ord(f.read(1))
>>> f.read(length)
'abcd'
like image 56
Mark Tolonen Avatar answered Sep 19 '22 19:09

Mark Tolonen


Writing and reading from a socket are separate. You can try to close a socket for writing and leave it open for reading.

See http://docs.python.org/library/socket.html#socket.socket.shutdown

Also, what FTP does is use two sockets: one for data, and one for this "confirmation".

You'd be happier using a second socket for this additional metadata.

like image 28
S.Lott Avatar answered Sep 20 '22 19:09

S.Lott


You don't actually want to use an 'EOF' marker if you intend to send any binary data through the pipe. What happens if your binary data happens to include that byte sequence? You could 'escape' it to prevent that from happening, but that requires you to check on both ends, and then make sure you escape your escape sequence as well.

If you are doing this for some kind of production system, look around to see if there's a networking API that you can use (something like FTP, HTTP, SFTP, etc).

If this is a school or small-scale project, what you need to do is write a communications protocol. The simplest might be for the sender to broadcast a single binary integer X (pick a data size, and stick with it), and then send X bytes of binary data. The receiver first snags the size, then only expects to receive that amount of data. Remember that if you need to send more bytes than the data size of X can send, you'll need to 'chunk' your data.

Also consider what happens when communications are lost mid-transfer. You can set timeouts on read(), but then you need to recover gracefully if communications resumes immediately after your timeout (although junking all of the data might be considered graceful, depending on the system).

like image 43
jkerian Avatar answered Sep 20 '22 19:09

jkerian