Тема: Клієт серверні додатки на Python
Всім доброго дня!
Отримав завдання написати клієнт сервер мовою програмування Python на протоколі передачі UDP з підтримкою алгоритму ARQ.
Потрібно переслати бінарний файл з клієнта на сервер за різних умов якості мережі.
Хочу попросити Вашої допомоги товариство, тому що зіткнувся з проблемами в логіці роботи моєї програми і не можу з цим впоратись.
Приводжу код клієна нижче...
from sys import argv as arguments
from sys import exit as end_program
from sys import stdin
from time import sleep as delay
from pickle import dumps
from pickle import loads
import socket
import os
import io
TIME_DELAY = {
"s": 1,
"ms": 1 * pow(10, -3),
"mcs": 1 * pow(10, -6),
"ns": 1 * pow(10, -9),
}
SOCKET = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
WINDOW_SIZE = 1000
BUFFER_SIZE = 1000
NUM_OF_DATA_BLOCK = 0
NUM_OF_DATA_BLOCK_COUNTER = 0
REQUEST = []
if len(arguments) != 3:
print('Alarm! Pass ip and port arguments')
end_program(1)
else:
DST_ADDR = arguments[1], int(arguments[2])
def get_block_from_stdin(_window_size=None, _buffer_size=None):
if _window_size is None:
_window_size = 500
if _buffer_size is None:
_buffer_size = 1400
global NUM_OF_DATA_BLOCK_COUNTER
NUM_OF_DATA_BLOCK_COUNTER += 1
_formed_block = []
for i in range(_window_size):
data = stdin.buffer.read(_buffer_size)
if data:
_formed_block.append(data)
else:
_formed_block.append(None)
break
return _formed_block
def flag_end():
print("END")
SOCKET.sendto(dumps("END"), DST_ADDR)
def sender(_formed_block):
for num_of_data_part, part_of_data in enumerate(_formed_block):
_numbered_formed_block = [NUM_OF_DATA_BLOCK, num_of_data_part, part_of_data]
# print(_numbered_formed_block)
SOCKET.sendto(dumps(_numbered_formed_block), DST_ADDR)
delay(TIME_DELAY["mcs"])
def resender(_formed_block, _request_list):
for index_of_data, data in enumerate(_formed_block):
for request_index in _request_list:
if index_of_data == request_index:
_request_block = [NUM_OF_DATA_BLOCK, index_of_data, data]
SOCKET.sendto(dumps(_request_block), DST_ADDR)
def answer_from_server():
_b_answer, DST_ADDR = SOCKET.recvfrom(BUFFER_SIZE)
_answer = loads(_b_answer)
return _answer
break_flag = True
while break_flag:
#numberpREQUESTet = 0
block_of_data = get_block_from_stdin(WINDOW_SIZE, BUFFER_SIZE)
if None in block_of_data:
block_of_data.pop()
break_flag = False
block_of_data_is_send_success = True
while block_of_data_is_send_success:
sender(block_of_data)
#"""
request = answer_from_server()
if request == "OK":
NUM_OF_DATA_BLOCK += 1
block_of_data_is_send_success = False
else:
resender(block_of_data, request)
# """
if not break_flag:
flag_end()
break
SOCKET.close()
print("Transmission is finished")
print("Blocks:", NUM_OF_DATA_BLOCK)
end_program()
а тут код серверу....
from sys import argv as arguments
from sys import exit as end_program
from sys import stdout
from time import sleep as delay
from pickle import dumps
from pickle import loads
import socket
import time
import os
HOST = "localhost"
PORT = 9000
#PORT = int(arguments[1])
SOCKET = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
SOCKET.bind((HOST, PORT))
WINDOW_SIZE = 1000
BUFFER_SIZE = 1020
NO_DATA = 0
def receive(_window_size=None, _buffer_size=None):
global _dst_addr
global NO_DATA
_packets = []
_data = ""
if _window_size is None:
_window_size = 500
if _buffer_size is None:
_buffer_size = 1400
for counter in range(_window_size):
try:
_data, _dst_addr = SOCKET.recvfrom(_buffer_size)
if _dst_addr:
SOCKET.settimeout(2)
_packet = loads(_data)
if _packet == "END":
_packets = _packet
break
elif _packet[1] == 999:
_packets.append(_packet)
break
else:
_packets.append(_packet)
NO_DATA = 0
except socket.timeout:
NO_DATA += 1
# print("\r[", NO_DATA, "]", SOCKET.gettimeout(), "sec after", end="")
return _packets, _dst_addr
wait = True
while wait:
received_window = [None for i in range(WINDOW_SIZE)]
success_receive = True
while success_receive:
#print("Wait for packets...")
packets, dst_addr = receive(WINDOW_SIZE, BUFFER_SIZE)
if packets == "END":
wait = False
else:
for packet in packets:
received_window[packet[1]] = [packet[1], packet[2]]
request = [index_of_data for index_of_data, data in enumerate(received_window) if index_of_data is None]
if len(request) == 0:
SOCKET.sendto(dumps("OK"), dst_addr)
for packet in received_window:
#print(packet)
#with open(NAME_FILE, "a") as FILE:
# FILE.write(packet[1])
stdout.buffer.write(packet[1])
success_receive = False
else:
SOCKET.sendto(dumps(request), dst_addr)
request = []
"""
retransmitted_packets = receive(len(request))
for retransmitted_packet in retransmitted_packets:
packet_number = retransmitted_packet[1]
received_window[packet_number] = [packet_number, retransmitted_packet[2]]
# """
SOCKET.close()
end_program()
Програма запускається за допомогою команд в консолі Linux:
python3 UDPclientl.py 127.0.0.1 9000 < 1.jpg(filename) - запуск клієта
python3 UDPserverl.py 9000 > new.jpg(filename) - запуск сервера
Бінарний файл генерується також в консолі за допомогою команд :
dd if=/dev/urandom of=file count=1024 bs=1048576 #generation 1gb
dd if=/dev/urandom of=file count=1024 bs=4096 #generation 4Mb file
Дуже прошу допомогти оскільки до здачі завдання залишилось всього 5 днів!!!
Зв'язатись можна через телеграм: @snnzr
або поштою snihurnazar@gmail.com
Винагороду обговоримо приватно)