|
4 | 4 | # but this is not a complete implementation! Yet it shows how a simple |
5 | 5 | # FTP client can be built, and you are welcome to extend it to suit |
6 | 6 | # it to your needs... |
| 7 | +# |
| 8 | +# How it works (assuming you've read the RFC): |
| 9 | +# |
| 10 | +# User commands are passed uninterpreted to the server. However, the |
| 11 | +# user never needs to send a PORT command. Rather, the client opens a |
| 12 | +# port right away and sends the appropriate PORT command to the server. |
| 13 | +# When a response code 150 is received, this port is used to receive |
| 14 | +# the data (which is written to stdout in this version), and when the |
| 15 | +# data is exhausted, a new port is opened and a corresponding PORT |
| 16 | +# command sent. In order to avoid errors when reusing ports quickly |
| 17 | +# (and because there is no s.getsockname() method in Python yet) we |
| 18 | +# cycle through a number of ports in the 50000 range. |
7 | 19 |
|
8 | 20 |
|
9 | 21 | import sys, posix, string |
@@ -60,12 +72,12 @@ def control(hostname): |
60 | 72 | # (Cycle through a number of ports to avoid problems with reusing |
61 | 73 | # a port within a short time.) |
62 | 74 | # |
63 | | -cycle = [0] |
| 75 | +nextport = 0 |
64 | 76 | # |
65 | 77 | def newdataport(s, f): |
66 | | - port = cycle[0] |
67 | | - cycle[0] = (port+1) % 16 |
68 | | - port = port + FTP_DATA_PORT |
| 78 | + global nextport |
| 79 | + port = nextport + FTP_DATA_PORT |
| 80 | + nextport = (nextport+1) % 16 |
69 | 81 | r = socket(AF_INET, SOCK_STREAM) |
70 | 82 | r.bind(gethostbyname(gethostname()), port) |
71 | 83 | r.listen(0) |
@@ -122,7 +134,7 @@ def getdata(r): |
122 | 134 | # |
123 | 135 | def getcommand(): |
124 | 136 | try: |
125 | | - return raw_input('ftp> ') |
| 137 | + return raw_input('ftp.py> ') |
126 | 138 | except EOFError: |
127 | 139 | return '' |
128 | 140 |
|
|
0 commit comments