-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
189 lines (145 loc) · 8.28 KB
/
server.py
File metadata and controls
189 lines (145 loc) · 8.28 KB
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import socket
import sys
import subprocess
LIMIT_LENGTH = 200 # limit total length of control message including file name
# Command line checks
if len(sys.argv) != 2:
print(f"Usage: python3 {sys.argv[0]} <Port Number>")
listenPort = int(sys.argv[1]) # listen to incoming connections on port (eg: 1234)
serverSideSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # create a server side socket
serverSideSock.bind(('', listenPort)) # bind the socket to the port
serverSideSock.listen(1) # start listening on the socket
def recvAll(sock, numBytes):
"""
From a specified socket, receive a specified number of bytes.
Return the total number of bytes received.
"""
recvBuff = "".encode() # receive buffer; convert string to bytes
tmpBuff = "".encode() # temporary buffer; convert string to bytes
while len(recvBuff) < numBytes: # receive complete data
tmpBuff = sock.recv(numBytes) # attempt to receive bytes
if not tmpBuff: # client has closed the socket
break
recvBuff += tmpBuff # add the received bytes to the buffer
return recvBuff
def sendAll(sock, anyData):
"""
From a specified socket, send specified number of bytes.
"""
numSent = 0
while len(anyData) > numSent:
numSent += sock.send(anyData[numSent:])
# Accept connections forever
while True:
print("Waiting for connections...")
clientControlSock, addr = serverSideSock.accept()
print("Accepted connection from client: ", addr,"\n")
clientSideSockIP = addr[0]
while True:
controlMessage = recvAll(clientControlSock, LIMIT_LENGTH)
input_string = controlMessage.strip()
serverDataSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if input_string == b'quit':
print("'quit' control message received from client; exiting the program\n")
break;
elif input_string[5:8] == b'get':
file_name = input_string[9:]
clientSideSockPort = int(input_string[0:5])
print("Waiting for client input ...")
serverDataSock.connect((clientSideSockIP, clientSideSockPort)) # connect to the client
try:
fileObj = open(file_name, "rb")
fileData = fileObj.read()
dataSize = len(fileData)
bytesSent = 0
sendAll(clientControlSock,"FILE FOUND".encode())
while bytesSent < dataSize: # Keep sending until all is sent
if bytesSent + 65536 < dataSize: # Read 65536 bytes of data
fileDataChunk = fileData[bytesSent:bytesSent+65536]
else:
fileDataChunk = fileData[bytesSent:]
bytesSent += 65536
dataSizeChunk = str(len(fileDataChunk)) # get the size of the data read and convert it to string
while len(dataSizeChunk) < 10: # prepend 0's to the size string until the size is 10 bytes << need for last chunk
dataSizeChunk = "0" + dataSizeChunk
fileDataChunk = dataSizeChunk.encode() + fileDataChunk # prepend the size of the data to the file data.
sendAll(serverDataSock, fileDataChunk)
fileObj.close()
controlMessage = clientControlSock.recv(10)
bytesTransfered = int(controlMessage.decode())
if dataSize == bytesTransfered:
print("File '", file_name.decode().strip(), "' successfully sent to client!\n")
else:
print("File '", file_name.decode().strip(), "' not sent to client...\n")
except FileNotFoundError:
print("File '", file_name.decode().strip(), "' not found! - FAILURE\n")
sendAll(clientControlSock,"FILE NOT FOUND".encode()) # file not found
serverDataSock.close()
elif input_string[5:8] == b'put':
file_name = input_string[9:]
clientSideSockPort = int(input_string[0:5])
print("Waiting for client input ...")
serverDataSock.connect((clientSideSockIP, clientSideSockPort)) # connect to the client
controlMessage = clientControlSock.recv(14) # check whether file is present or not
input_string = controlMessage.strip()
if input_string == b'FILE NOT FOUND':
print("File not found! - FAILURE\n")
continue
bytesReceived = 0
while True:
chunkData = "" # The buffer to all data received from the the client.
chunkSizeBuff = "" # The buffer containing the chunk size
chunkSizeBuff = recvAll(serverDataSock, 10) # Receive the first 10 bytes indicating the size of the chunk
chunkSize = int(chunkSizeBuff) # Get the chunk size
bytesReceived += chunkSize # append chunk size to bytes received
if chunkSize == 0:
print("File does not exist from client!\n")
break
chunkData = recvAll(serverDataSock, chunkSize) # Get chunk data
if bytesReceived <= 65536: # first chunk
file = open(file_name, 'wb') # create file and write
else:
file = open(file_name, 'ab') # append
file.write(chunkData)
file.close()
if chunkSize < 65536: # check if it is last chunk
break;
serverDataSock.close()
sendAll(clientControlSock,str(bytesReceived).encode())
controlMessage = clientControlSock.recv(10)
testInt = int(controlMessage.decode())
if testInt == bytesReceived:
print("File '", file_name.decode().strip(), "' successfully received from client!\n")
else:
print("File '", file_name.decode().strip(), "' not received from client...\n")
elif input_string[5:7] == b'ls':
clientSideSockPort = int(input_string[0:5])
print("Waiting for client input ...")
serverDataSock.connect((clientSideSockIP, clientSideSockPort)) # connect to the client
fileData = subprocess.check_output(["ls -l"], shell=True)
dataSize = len(fileData)
bytesSent = 0
while bytesSent < dataSize:
if bytesSent + 65536 < dataSize:
fileDataChunk = fileData[bytesSent:bytesSent+65536]
else:
fileDataChunk = fileData[bytesSent:]
bytesSent += 65536
dataSizeChunk = str(len(fileDataChunk))
while len(dataSizeChunk) < 10: # prepend 0's to the size string until its size is 10 bytes
dataSizeChunk = "0" + dataSizeChunk
fileDataChunk = dataSizeChunk.encode() + fileDataChunk # prepend the size of the data to the file data
sendAll(serverDataSock, fileDataChunk)
sendAll(clientControlSock,str(dataSize).encode()) # check if client received data completely
controlMessage = recvAll(clientControlSock, 7)
input_string = controlMessage.strip()
if input_string == b'SUCCESS':
print("ls command output sent successfully!!\n")
else:
print("ls command output error...\n")
serverDataSock.close()
else:
break
clientControlSock.close()
print("Connection closed from client: ", addr, "\n")
break