Last active
September 19, 2020 07:53
-
-
Save kezzyhko/935667f75c9f0f9d73b1a8573aa5baff to your computer and use it in GitHub Desktop.
Python client and server to send and receive files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
import sys | |
import os | |
# check arguments | |
def assert_(cond, message = None, print_help=True): | |
if (not cond): | |
if (message): | |
print() | |
print(message) | |
print() | |
if (print_help): | |
print(" Usage: {} file domain-name|ip-address port-number".format(sys.argv[0])) | |
print("Example: {} meme.png your_vps.ru 8800".format(sys.argv[0])) | |
print("Example: {} video.mp4 18.33.12.49 9332".format(sys.argv[0])) | |
exit(0) | |
assert_(len(sys.argv) == 4, "Wrong number of arguments") | |
assert_(os.path.isfile(sys.argv[1]), "Could not open file {}".format(sys.argv[1])) | |
# connect to server | |
try: | |
s = socket.socket() | |
s.connect((sys.argv[2], int(sys.argv[3]))) | |
except socket.error: | |
assert_(False, "Could not connect to server {}:{}".format(sys.argv[2], sys.argv[3])) | |
# send filename | |
s.send(sys.argv[1].rpartition('/')[2].encode('utf-8')) | |
s.send(b'\x00') | |
# send the file itself | |
try: | |
data_sent = 0 | |
file_size = os.path.getsize(sys.argv[1]) | |
with open(sys.argv[1], 'rb') as f: | |
while True: | |
data = f.read(1024) | |
if (not data): break | |
s.send(data) | |
data_sent += len(data) | |
print("Sent {} out of {} bytes of data ({}%)".format(data_sent, file_size, data_sent/file_size*100)) | |
except IOError: | |
assert_(False, "Unknown IO error happened", False) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This code is based on server_threads.py example from here: | |
# https://gist.github.com/gordinmitya/349f4abdc6b16dc163fa39b55544fd34 | |
import socket | |
import sys | |
import os | |
from threading import Thread | |
# thread to listen one particular client | |
class ClientListener(Thread): | |
def __init__(self, sock: socket.socket): | |
super().__init__(daemon=True) | |
self.sock = sock | |
self.file = None | |
def assert_(self, cond, message = None): | |
if (not cond): | |
if (message): | |
self.sock.send(message.encode('utf-8')) | |
print(message) | |
self.sock.close() | |
print(self.name + ' disconnected') | |
if (self.file): | |
self.file.close() | |
sys.exit() | |
def run(self): | |
print("Client's thread:", self.name) | |
# Revieve user filename and part of data | |
name_and_data = self.sock.recv(1024) | |
self.assert_(b'\x00' in name_and_data, | |
"Name of file is too long" if len(name_and_data) == 1024 else "Reveived data is in wrong format") | |
name_and_data = name_and_data.partition(b'\x00') # separate name from data | |
data = name_and_data[2] | |
user_filename = name_and_data[0].decode('utf-8').rpartition('/')[2] | |
# Check for filename collisions | |
real_filename = user_filename | |
user_filename = user_filename.rpartition('.') # to separate the extension | |
i = 0 | |
while (os.path.isfile(real_filename)): | |
i+=1 | |
real_filename = "{}_copy{}.{}".format(user_filename[0], i, user_filename[2]) | |
# Try to create file | |
try: | |
self.file = open(real_filename, 'wb') | |
except IOError: | |
self.assert_(False, "Could not create file {}".format(real_filename)) | |
# Save data to the file | |
while True: | |
self.file.write(data) | |
data = self.sock.recv(1024) | |
if (not data): break | |
# Finish the thread | |
self.assert_(False) | |
# main part | |
def main(): | |
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP | |
# sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
sock.bind(('', 8800)) | |
sock.listen() | |
while True: | |
# blocking call, waiting for new client to connect | |
conn, addr = sock.accept() | |
print('New client connected:', str(addr)) | |
ClientListener(conn).start() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment