Skip to main content
GameDev.net gamedev.net
🔒 Locked

Writing Files to a Remote Client in Python

Started by PhlashStudios Mar 16, 2006 at 11:14 AM 17 replies 2.8k views
Original Post
PhlashStudios
PhlashStudios
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]
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
Redleaf
Redleaf
Straying from your technical question slightly, if you really want to see python's power when it comes to network programming, maybe you should give twisted-matrix a try. Your file-sharing app might be much easier to write this way.
PhlashStudios
PhlashStudios
Thanks, do you know where I can get any good tutorials...besides buying the book? Especially if they pertain to file sharing.
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
Redleaf
Redleaf
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.
Kylotan
Kylotan
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.
PhlashStudios
PhlashStudios
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?
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
Flarelocke
Flarelocke
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.
---New infokeeps brain running;must gas up!
PhlashStudios
PhlashStudios
What about if the file is for instance a picture or a music file?
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
Kylotan
Kylotan
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.
PhlashStudios
PhlashStudios
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 itimport socketISSocket = 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 savesimport socketISSocket = 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.
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
PhlashStudios
PhlashStudios
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]
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
Flarelocke
Flarelocke
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.
---New infokeeps brain running;must gas up!
PhlashStudios
PhlashStudios
Ya, I tried that, I took out the q and did a sendall with the read, except parts of my file were still untransmited. What can i do to make sure everything is sent and received?
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
Kylotan
Kylotan
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.
PhlashStudios
PhlashStudios
Thanks a lot...What do you mean by update it and how do I fix it?
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
PhlashStudios
PhlashStudios
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 savesimport socketISSocket = 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 itimport socketISSocket = 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]
<a href="http://eyeredux.com/campaigns/1/redirect">Hello!</a>
Flarelocke
Flarelocke
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.
---New infokeeps brain running;must gas up!
Kylotan
Kylotan
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.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.