Python Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesPython Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
AT&T devCentral & BlackBerry(r) Webcast Series: BlackBerry and GPS -Build Location Awareness into your BlackBerry Applications, July 10th-1:00PM EST. Register Today!
  #1  
Old March 9th, 2004, 05:42 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Sending a file using sockets

Does anyone know how to properly send a file using sockets? At the moment I am using this:

Code:
sock.sendall(somefile.read())


and

Code:
input = sock.recv(1024)


on the other end. It works for simple stuff like tiny text files (well anything under 1024 bytes) but it's obviously not going to work for something like an mp3. Am I supposed to loop my recv until I get a 0?

Reply With Quote
  #2  
Old March 10th, 2004, 03:18 AM
DevCoach DevCoach is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2004
Location: London, England
Posts: 1,193 DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 1 Week 5 Days 12 h 59 m 24 sec
Reputation Power: 252
It has been a while since I have done any programming with raw sockets, but I think you are right, loop until recv returns zero. The example in the docs does exactly that.

An alternative way is to create a file-like object from the socket, and read from it exactly like you would a file. From the docs for the socket object:

Quote:
makefile( [mode[, bufsize]])

Return a file object associated with the socket. (File objects are described in 2.3.8, ``File Objects.'') The file object references a dup()ped version of the socket file descriptor, so the file object and socket object may be closed or garbage-collected independently. The socket should be in blocking mode. The optional mode and bufsize arguments are interpreted the same way as by the built-in file() function; see ``Built-in Functions'' (section 2.1) for more information.


Hope this helps.

Dave - The Developers' Coach

Reply With Quote
  #3  
Old March 10th, 2004, 04:30 AM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
I only know ftp:
The ftplib uses sendall for sending
and the following code snippet for receiving:
Code:
        while 1: 
            data = conn.recv(blocksize)
            if not data: 
                break
            callback(data)
        conn.close()

(The callback is used to write the data to a file).

sendall manages the transfer - splitting the large block of data into smaller blocks and sending/resending as necessary until all is received, the data will be passed up to your higher level in the correct sequence although the order in which it is actually received may be different.

FTP obviously wraps this in a protocol so that both sides of the conversation know what to expect. Before the transfer there is an exchange of commands and acknowledgements. The problem is it's dedicating the connection for file transfer. You have no clean way to interrupt it.
One solution is to create a second socket connection just for file transfer (this is what ftp does) leaving the original socket for commands and other traffic
Code:
From RFC 959
                                            -------------
                                            |/---------\|
                                            ||   User  ||    --------
                                            ||Interface|<--->| User |
                                            |\----^----/|    --------
                  ----------                |     |     |
                  |/------\|  FTP Commands  |/----V----\|
                  ||Server|<---------------->|   User  ||
                  ||  PI  ||   FTP Replies  ||    PI   ||
                  |\--^---/|                |\----^----/|
                  |   |    |                |     |     |
      --------    |/--V---\|      Data      |/----V----\|    --------
      | File |<--->|Server|<---------------->|  User   |<--->| File |
      |System|    || DTP  ||   Connection   ||   DTP   ||    |System|
      --------    |\------/|                |\---------/|    --------
                  ----------                -------------

                  Server-FTP                   USER-FTP

One alternative could be to use "inband" commands. In this scenario you can do something like put an info-field at the head of every packet which states it's purpose - either a command or a file packet. The file-data block you want to send will be split into sub-blocks by you and you use send() or sendall() to send each sub-block. It becomes your job to untangle the packets and re-order the sub-blocks if necessary. This way you socket is not locked when the file transfer fails - you still keep the chat going. This assumes that your receiving socket is not being battered by a rogue file sender of course.

If you wrap this concept into a virtual socket class then you might have something that is very useful. By this I mean taking one "physical" socket object and allowing 'n' virtual connections to multiplex over it. This idea is used in "tunnelling" situations where routes through firewalls are needed or you only allow secure connections like ssh. This would allow anything you like - chat, file transfer, buddy lists etc.

I know my msn client cannot work through my firewall for anything other than simple chat because of the need to create additional peer to peer socket connections for the actual transfer. A solution to this would be to allow all data transfers to go via the main server but this obviusly puts extra load on the server which is why they don't do it.

Anyone know other "solutions"?

Grim
__________________
*** Experimental Python Markup CGI V2 ***

Reply With Quote
  #4  
Old March 11th, 2004, 05:01 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
That's a cool idea Grim, I'll look into it later. Btw, thanks for both of your replys .

Reply With Quote
  #5  
Old March 28th, 2004, 03:49 AM
CCDemonX's Avatar
CCDemonX CCDemonX is offline
WebDeveloper++;
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2003
Location: New York City
Posts: 85 CCDemonX User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
I was playing around with sockets a few weeks ago. heres two scripts i came up with. one is the server, the other is the client. you need to run the server script then call the client script with relative file as the first argument to the script.

Code:
# USAGE: python FileSender.py [file]

import sys, socket

HOST = 'localhost'
CPORT = 9091
MPORT = 9090
FILE = sys.argv[1]

cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cs.connect((HOST, CPORT))
cs.send("SEND " + FILE)
cs.close()

ms = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ms.connect((HOST, MPORT))

f = open(FILE, "rb")
data = f.read()
f.close()

ms.send(data)
ms.close()



Code:
# USAGE: python FileReciever.py

import socket, time, string, sys, urlparse
from threading import *

#------------------------------------------------------------------------

class StreamHandler ( Thread ):

    def __init__( this ):
        Thread.__init__( this )

    def run(this):
        this.process()

    def bindmsock( this ):
        this.msock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        this.msock.bind(('', 9090))
        this.msock.listen(1)
        print '[Media] Listening on port 9090'

    def acceptmsock( this ):
        this.mconn, this.maddr = this.msock.accept()
        print '[Media] Got connection from', this.maddr
    
    def bindcsock( this ):
        this.csock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        this.csock.bind(('', 9091))
        this.csock.listen(1)
        print '[Control] Listening on port 9091'

    def acceptcsock( this ):
        this.cconn, this.maddr = this.csock.accept()
        print '[Control] Got connection from', this.maddr
        
        while 1:
            data = this.cconn.recv(1024)
            if not data: break
            if data[0:4] == "SEND": this.filename = data[5:]
            print '[Control] Getting ready to receive "%s"' % this.filename
            break

    def transfer( this ):
        print '[Media] Starting media transfer for "%s"' % this.filename

        f = open(this.filename,"wb")
        while 1:
            data = this.mconn.recv(1024)
            if not data: break
            f.write(data)
        f.close()

        print '[Media] Got "%s"' % this.filename
        print '[Media] Closing media transfer for "%s"' % this.filename
    
    def close( this ):
        this.cconn.close()
        this.csock.close()
        this.mconn.close()
        this.msock.close()

    def process( this ):
        while 1:
            this.bindcsock()
            this.acceptcsock()
            this.bindmsock()
            this.acceptmsock()
            this.transfer()
            this.close()

#------------------------------------------------------------------------

s = StreamHandler()
s.start()

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesPython Programming > Sending a file using sockets


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump


Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 2 hosted by Hostway