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
