Sign in to follow this  
PhlashStudios

Writing Files to a Remote Client in Python

Recommended Posts

Hey everyone, I am working with Python and am trying to create a simple file sharing app using a client/server model, to test out its network capabilities. I have everything working fine with the login/username/password but have come up against a brick wall in the actual file-share department. My idea was to use the open(~) command to open a file on the server and then the write(~) command to write that file to the client. The problem is actually writing the file to the client, can anyone help? I am not using any packages like SimpleXMLRPCServer, just sockets. Thanks in advance. [Edited by - PhlashStudios on March 16, 2006 11:39:29 AM]

Share this post


Link to post
Share on other sites
Good question. I forget the exact path I took while learning to use twisted. I would begin by reading some of the core developer how-to guides. I don't recommend reading them all, or even from top to bottom, as a lot of that information probably won't be important to you. I think I started with Perspective Broker, which will probably be the kind of network programming you're looking for.

Share this post


Link to post
Share on other sites
You've not given much detail with the problem. Which part do you not know how to do? On one side you open the file, and send it down an open socket, repeating calls to send() until it's all done, then close the socket. On the other side you create a file, read from the socket, repeating calls to recv() until you receive zero or an exception, then write that data to the file.

If you're really just experimenting to learn Python networking, start with something less ambitious and just send messages from one machine to the other. Once you have that working, file transfer is the next step.

Share this post


Link to post
Share on other sites
The part that is not working for me, is when I try to send the file to the socket it tells me that I can't send whole files and I'm not sure how to break it up, could you provide some example code?...Like for example sending a text file from the server to the client?

Share this post


Link to post
Share on other sites
Dunno if this is what you want, but there's a sendall() method of socket objects that will keep trying to send until it's done or an error occurs.

You may also be getting the error because a file is not a string, which is what socket.send() expects. Use file.read() to retrieve the string contained in the file.

Share this post


Link to post
Share on other sites
A file is a file. It's a long list of bytes on a disk, and your programming language doesn't care what it actually might mean to other applications. All it has to do is pick those bytes off the disk and send them down the socket.

Share this post


Link to post
Share on other sites
I tried to write a simple client server interface to test out the idea and what kept happening is that I would receive a file called test.bmp, but the file was blank....
server:

#test file transfer server


#server listens for connections from a client and when a client connects sends a #picture to it

import socket

ISSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ISSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ISSocket.bind(('', 1337))
ISSocket.listen(1)

while 1:
clientsock, clientaddr = ISSocket.accept()
print "Got connection from ", clientsock.getpeername()
clientsock.sendall('q')
print "this far"
file1 = open("C:\Documents and Settings\Dan Shipper\My Documents\My Pictures\mole.bmp", "w+")
for line in file1:
clientsock.sendall(line)
print "file sent"





client:

#test file transfer client


#client connects to the server which transfers an image to client, client saves

import socket

ISSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ISSocket.connect(('192.168.1.65', 1337))

while 1:
try:
buf = ISSocket.recv(10000)
except socket.error, e:
print "error recieveing data"
if not len(buf):
print "not len buf"
break
file1 = open("test.bmp", "a+")
file1.write(buf)
print "file written"
print buf



Any ideas? thanks in advance
Edit: Also the files that I am trying to send turn up empty, they are still there, just with no bites left in them.

Share this post


Link to post
Share on other sites
I changed the way the file was opened to 'r' and it sent it, but now Photoshop can't open it, it says it can't parse the file. Any ideas?

Edit: I checked the size of the sent file and the orginal file and the sent file is 257 kb while the original file is 900 kb. So that means that all of the data isn't getting sent or isnt getting received. But how do I fix this?

[Edited by - PhlashStudios on March 17, 2006 3:48:34 PM]

Share this post


Link to post
Share on other sites
The file as received will have a 'q' character at the beginning, and all the linebreaks have been taken out when split into lines. Just use clientsock.sendall(file1.read()) instead of the for loop. It's not a text-file, so splitting the file into lines is usually not a good idea.

Share this post


Link to post
Share on other sites
You're opening the file wrongly in 3 ways: firstly, it should be for reading not writing, secondly you shouldn't be saying you're going to update it, and thirdly you should specify a binary read. Try "rb" instead of "w+" in the server.

Also you shouldn't keep opening the file in the receive loop - open it once before the while loop. Then your hard disk won't have to work so hard.

Share this post


Link to post
Share on other sites
I updated the code as per your suggestion and ran it, and the whole file showed up this time and I thought everything was fine. The icon for the file even had a drawing of the bmp that was inside. But when I tried to open it, Windows Picture and Fax viewer said drawing failed, and Photoshop said it couldn't open it because of a disk error. Anyone know what went wrong? Heres the code....
Client:

#test file transfer client


#client connects to the server which transfers an image to client, client saves

import socket

ISSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ISSocket.connect(('192.168.1.65', 1337))
ISSocket.sendall('Please send file now...')
while 1:

buf = ISSocket.recv(100000)

if not len(buf):
print "not len buf"
file1 = open("test.bmp", "a+")
file1.write(buf)
print "file written"
print buf






Server:

#test file transfer server


#server listens for connections from a client and when a client connects sends a picture to it

import socket

ISSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ISSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ISSocket.bind(('', 1337))
ISSocket.listen(1)
file1 = open("C:\Documents and Settings\Dan Shipper\My Documents\My Pictures\lard-muffinn.bmp", "rb")

while 1:
clientsock, clientaddr = ISSocket.accept()
print "Got connection from ", clientsock.getpeername()
buf = clientsock.recv(1000)
print buf
## for line in file1:
## print line
## clientsock.sendall(line)
## print "file sent"
clientsock.sendall(file1.read())



Edit: I did a more careful check for file size and it turns out there is a discrepency of a few kilobytes. Could it be because the buffer isn't full, it isn't writing the last bit of data?

[Edited by - PhlashStudios on March 18, 2006 9:12:28 AM]

Share this post


Link to post
Share on other sites
Fixing the code per his suggestion would be something like: (client code)


file1 = open("test.bmp", "w+")
while 1:
...


There's a chance that your bytes are missing because the buffer isn't getting properly flushed when the file object is garbage collected each time, so moving it outside the loop could help. If it's the case, then you'll want to properly close the file and/or flush it before it disappears.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I don't know much about Phyton, but to me it looks like you aren't creating the file as a binary file on the receiving end.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
I don't know much about Phyton, but to me it looks like you aren't creating the file as a binary file on the receiving end.


Yeah, that looks to be the case, and I should have spotted that the first time around.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this