Skip to content

Instantly share code, notes, and snippets.

@kezzyhko
Last active September 19, 2020 07:53
Show Gist options
  • Save kezzyhko/935667f75c9f0f9d73b1a8573aa5baff to your computer and use it in GitHub Desktop.
Save kezzyhko/935667f75c9f0f9d73b1a8573aa5baff to your computer and use it in GitHub Desktop.
Python client and server to send and receive files
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 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