Skip to content
This repository has been archived by the owner on Sep 9, 2021. It is now read-only.

Kostarev Vladislav, 203, lab_1b #158

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import socket
import threading
import time
import sys
import os
import errno


if len(sys.argv) != 3:
print("Select IP and server port!")
sys.exit()

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((sys.argv[1], int(sys.argv[2])))
client_socket.setblocking(False)

my_nick = input("Your nickname: ")
nickname = my_nick.encode('ascii')
nickname_header = len(nickname).to_bytes(5, byteorder='big')
client_socket.send(nickname_header + nickname)


def get_package(sock):
header = sock.recv(5)

if not len(header):
print('Connection was closed by server')
client_socket.close()
os._exit(0)

length = int.from_bytes(header, byteorder='big', signed=False)

return sock.recv(length).decode('ascii')


def receiving():
while True:
try:
nick = get_package(client_socket)
message = get_package(client_socket)

if message == f'Nickname {nick} is already in use!':
print(message)
print('Please log in to the chat again with a new nickname')
client_socket.close()
os._exit(0)

print('<{}> [{}] {}'.format(time.strftime('%H:%M', time.localtime()), nick, message))

# for blocking sockets
except IOError as e:
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print('Reading error: {}'.format(str(e)))
client_socket.close()
sys.exit()


def sending():
while True:
try:
message = input()

if message:
enc_message = message.encode('ascii')
message_header = len(enc_message).to_bytes(5, byteorder='big')
client_socket.send(message_header + enc_message)
# print('<{}> [{}] {}'.format(time.strftime('%H:%M', time.localtime()), my_nick, message))
except KeyboardInterrupt:
os._exit(0)


receive_thread = threading.Thread(target=receiving)
receive_thread.daemon = True
receive_thread.start()

sending()
91 changes: 91 additions & 0 deletions server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import socket
import select
import sys


if len(sys.argv) != 3:
print("Select IP and port")
sys.exit()


ip = sys.argv[1]
port = int(sys.argv[2])


server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((ip, port))
server.listen()
sockets_list = [server] # list of sockets
clients = {} # list of connected clients
print(f'Server online')


def broadcast(sock, nick, msg, header):
for tmp in clients:
if tmp != sock:
tmp.send(nick['header'] + nick['data'] + header + msg)


def receive_message(sock):
try:
header = sock.recv(5)
except ConnectionResetError:
return False

if not len(header):
return False

length = int.from_bytes(header, byteorder='big', signed=False)

return {'header': header, 'data': sock.recv(length)}


def close_connection(sock):
nick = clients[sock]
print(f"Connection from {clients[sock]['data'].decode('ascii')} was closed")
data = f"{nick['data'].decode('ascii')} left the chat".encode('ascii')
header = len(data).to_bytes(5, byteorder='big')

broadcast(some_socket, nick, data, header)

sockets_list.remove(sock)
del clients[sock]


while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], sockets_list)

for some_socket in read_sockets:
if some_socket == server:
client_socket, client_address = server.accept()
nickname = receive_message(client_socket)

if nickname is False:
continue

if nickname in clients.values():
ms = f"Nickname {nickname['data'].decode('ascii')} is already in use!".encode('ascii')
header = len(ms).to_bytes(5, byteorder='big')
client_socket.send(nickname['header'] + nickname['data'] + header + ms)
continue

sockets_list.append(client_socket)
clients[client_socket] = nickname

print(f"{nickname['data'].decode('ascii')} was connected from {client_address}")

message = f"{nickname['data'].decode('ascii')} joined!".encode('ascii')
message_header = len(message).to_bytes(5, byteorder='big')

broadcast(client_socket, nickname, message, message_header)

else:
message = receive_message(some_socket)

if message is False:
close_connection(some_socket)
continue

nickname = clients[some_socket]
broadcast(some_socket, nickname, message['data'], message['header'])