recv.py 4.97 KB
Newer Older
wx002's avatar
wx002 committed
1 2
from socket import *
import re
wx002's avatar
wx002 committed
3
import base64
wx002's avatar
wx002 committed
4 5
import linecache
import sys
wx002's avatar
wx002 committed
6 7
from datetime import datetime
import argparse
wx002's avatar
wx002 committed
8

wx002's avatar
wx002 committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

def get_argus():
    '''
    gets the arguements
    :return:
    '''
    parser = argparse.ArgumentParser(
        description="Receiver For RDT stop and wait with checksum"
    )
    parser.add_argument('--addr',
                        default='127.0.0.1',
                        help='The address of the sender to listen to')
    parser.add_argument('--port',
                        default=8888, type=int,
                        help='The port of the sender to listen to')
    return parser.parse_args()

argus = get_argus()
addr = argus.addr
port = argus.port
dest = (addr, port)
wx002's avatar
wx002 committed
30
currentIndex = -1
wx002's avatar
wx002 committed
31 32 33 34 35 36
sock = socket(AF_INET, SOCK_DGRAM)

sock.bind(dest)

fileList = []
lineStr = ''
wx002's avatar
wx002 committed
37

wx002's avatar
wx002 committed
38

wx002's avatar
wx002 committed
39
def PrintException():
wx002's avatar
wx002 committed
40 41 42 43 44
    '''
    Print detail exception details
    taken from: https://stackoverflow.com/questions/14519177/python-exception-handling-line-number
    :return:
    '''
wx002's avatar
wx002 committed
45 46 47 48 49 50 51 52 53
    exc_type, exc_obj, tb = sys.exc_info()
    f = tb.tb_frame
    lineno = tb.tb_lineno
    filename = f.f_code.co_filename
    linecache.checkcache(filename)
    line = linecache.getline(filename, lineno, f.f_globals)
    print ('EXCEPTION IN ({}, LINE {} "{}"): {}'.format(filename, lineno, line.strip(), exc_obj))


wx002's avatar
wx002 committed
54

wx002's avatar
wx002 committed
55

wx002's avatar
wx002 committed
56
def get_decode_list(byteString):
wx002's avatar
wx002 committed
57 58 59
    # print("byteString: {}\tType: {}".format(byteString, type(byteString)))
    # string = byteString.decode('utf-8')
    stringList = re.split('\t', byteString, maxsplit=2)
wx002's avatar
wx002 committed
60 61
    return stringList

wx002's avatar
wx002 committed
62 63 64 65 66 67 68 69

def verify_packet_content(stringList):
    '''
    index 0: header index
    index 1: content hashed form in base64
    index 2: actual data
    '''
    try:
wx002's avatar
wx002 committed
70 71 72 73 74 75 76
        if stringList[1] != None and stringList[2] != None:
            encoded_str = base64.b64decode(bytes(stringList[1], 'utf-8')).decode('utf-8')
            if encoded_str == stringList[2]:
                return True
        else:
            return False

wx002's avatar
wx002 committed
77 78
    except Exception:
        return False
wx002's avatar
wx002 committed
79 80


wx002's avatar
wx002 committed
81
startTime = datetime.now()
wx002's avatar
wx002 committed
82 83

print('established connection with server, waiting to receive...')
wx002's avatar
wx002 committed
84
while True:
Alan Marchiori's avatar
Alan Marchiori committed
85
    data, addr = sock.recvfrom(1048)  # why 1048? what if a line is longer than 1048 bytes?
wx002's avatar
wx002 committed
86

wx002's avatar
wx002 committed
87
    #print("recv data: {}".format(data))
wx002's avatar
wx002 committed
88
    while data != b'####' and data != b'END':
wx002's avatar
wx002 committed
89 90 91 92
        try:
            lineStr += data.decode('utf-8')
        except Exception:
            # bad packet ask for resend
wx002's avatar
wx002 committed
93
            sock.sendto(b'NNNN', addr)
wx002's avatar
wx002 committed
94
        # print(get_decode_list(lineStr))
wx002's avatar
wx002 committed
95
        data, addr = sock.recvfrom(1048)
Alan Marchiori's avatar
Alan Marchiori committed
96

wx002's avatar
wx002 committed
97
    if data == b'####':
wx002's avatar
wx002 committed
98
        #print('Got line end!')
wx002's avatar
wx002 committed
99
        packetList = get_decode_list(lineStr)
wx002's avatar
wx002 committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
        try:
            index = int(base64.b64decode(packetList[0].encode()))
            print('Got packet index {}\t Expecting packet index {}'.format(index, currentIndex+1))
            if index == currentIndex + 1:
                print('index match, verfying packet!')
                # verify content
                # print(verify_packet_content(packetList))
                if verify_packet_content(packetList):
                    fileList.append(packetList[2])
                    # update currentIndex
                    currentIndex += 1
                    print("Got packet! Recv Index: {}\tNext index: {}\tCurrentLine: {}".format(index, currentIndex+1,
                                                                                               packetList[2]))
                    print('sending ACK...')
                    sock.sendto(b'ACK\t'+ base64.b64encode(str(index).encode()), addr)
wx002's avatar
wx002 committed
115

wx002's avatar
wx002 committed
116 117 118 119 120 121 122 123 124
                    # print('recvived 1 line!')
                else:
                    # corrupted content, ask for the same line again
                    print('packet {} is corrupted, ask for line again!'.format(index))
                    sock.sendto(b'NNNN', addr)
            elif index == currentIndex and len(packetList) == 3:  # duplicated packet, resend ack
                print('resending ACK for packet index {}, next packet index is {}'.format(index, currentIndex+1))
                sock.sendto(b'ACK\t'+base64.b64encode(str(currentIndex).encode()), addr)
            else:
wx002's avatar
wx002 committed
125 126
                print('packet error for index {} and current index {}! Ask for resend!',
                      format(str(index), str(currentIndex)))
wx002's avatar
wx002 committed
127
                sock.sendto(b'NNNN', addr)
wx002's avatar
wx002 committed
128
            lineStr = ''
wx002's avatar
wx002 committed
129 130 131
        except:
            print(index, packetList)
            PrintException()
wx002's avatar
wx002 committed
132
        # print(fileList)
wx002's avatar
wx002 committed
133
        #lineStr = ''
wx002's avatar
wx002 committed
134 135
        # data = ''
        #print(fileList)
wx002's avatar
wx002 committed
136

wx002's avatar
wx002 committed
137

wx002's avatar
wx002 committed
138 139 140

    if data == b'END':
        print("got all contents!")
wx002's avatar
wx002 committed
141
        sock.sendto(b'END', addr)
wx002's avatar
wx002 committed
142 143
        sock.close()
        # make file
wx002's avatar
wx002 committed
144
        file = open('recvData/recv.txt', 'w+')
wx002's avatar
wx002 committed
145
        file.writelines(fileList)
wx002's avatar
wx002 committed
146
        file.close()
wx002's avatar
wx002 committed
147 148 149 150 151 152
        endTime = datetime.now()
        # print total time in sec
        total_time = (endTime-startTime).total_seconds()
        print('total time: {}'.format(total_time))
        file_size = 167546
        print('Transfer rate: {} bytes per second'.format(file_size/total_time))
wx002's avatar
wx002 committed
153
        exit(0)