-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathftclient
144 lines (106 loc) · 3.15 KB
/
ftclient
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/python
# Morgan Brenner
# CS 372 Program 2
import signal
import socket
import os, sys
def checkArgs(argv):
#check # of args
if len(argv) < 5:
return 1
#check for valid command
elif argv[3] != '-l' and argv[3] != '-g' :
return 1
#ports are numbers, not reserved ports, or out of range
elif argv[2].isdigit() == False or int(argv[2]) < 1024 or int(argv[2]) > 65535:
return 1
elif argv[len(argv) - 1].isdigit() == False or int(argv[len(argv) - 1]) < 1024 or int(argv[len(argv) - 1]) > 65535:
return 1
#check for file name
elif argv[3] == '-g' and len(argv) < 6:
return 1
else:
return 0
def initiateContact(argv):
"""
Returns: socket file descriptor for control connection
"""
HOST = argv[1]
PORT = int(argv[2])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
return s
def startUp(port):
"""
Returns: socket file descriptor for data connection
"""
q = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
q.bind(('', port))
q.listen(1) #allow 1 connection at a time
return q
def makeRequest(s, argv):
"""
Parses and formats command, sends to server via ctrl connection
"""
if argv[3] == '-l':
cmd = ' '.join(argv[3:len(argv)])[1:] #join args with spaces, trim '-' from option
s.send(cmd)
q = startUp(int(argv[4])) #wait for file list
conn, addr = q.accept()
response = conn.recv(1000)
print 'Receiving directory structure from ' + argv[1] + ':' + argv[2]
print response #show directory listing
conn.close()
elif argv[3] == '-g':
cmd = ' '.join(argv[3:len(argv)])[1:] #join args with spaces, trim '-' from option
s.send(cmd)
#HANDLE FILE NOT FOUND
ok = s.recv(1000)
if 'ok' not in ok:
print ok #should be error message
return
q = startUp(int(argv[5])) #wait for files
s.send('ok')
conn, addr = q.accept()
receiveFile(conn, argv)
conn.close()
return
def receiveFile(conn, argv):
"""
Repeatedly receives 1000-byte chunks of string from server on data connection,
and stores them in the appropriate file
"""
print 'Receiving ' + '\"' + argv[4] + '\" from ' + argv[1] + ':' + argv[2]
#handle duplicate file names
if isDuplicateFile(argv[4]):
print 'duplicate file name'
return
f = open(argv[4], 'w+')
response = ''
while '@@' not in response: #'@@' from server signals end of transfer
f.write(response)
response = ''
response = conn.recv(1000)
print 'transfer complete'
f.close()
return
def isDuplicateFile(fileName):
dir = os.listdir('.')
return fileName in dir
def sigint_handler(signal, frame):
"""
sigint handler for closing server program cleanly
"""
print "\nexiting ftclient"
sys.exit(0)
signal.signal(signal.SIGINT, sigint_handler)
if __name__ == "__main__":
#validate command line parameters
if checkArgs(sys.argv):
print 'USAGE: ./ftclient <SERVER_HOST> <SERVER_PORT> <COMMAND> [FILENAME] <DATA_PORT>'
exit(1)
#establish TCP control connection on <SERVER_PORT>, i.e., connection P
s = initiateContact(sys.argv)
makeRequest(s, sys.argv)
s.close()