예제 #1
0
class CThread(threading.Thread):
    def __init__(self, c_sock, c_addr, file='out/serverTimeData.txt'):
        threading.Thread.__init__(self)                         # create a new thread
        self._socket = c_sock
        self._addr = c_addr
        self._socket.setblocking(False)                         # non-blocking mode
        print('A Client has connected at address:\t', self._addr)
        self._ts = TimeStamp(datetime.datetime.now())
        self._file = open(file, 'a')

    """ Send a TimeStamp, if it is time to do so. """
    def _send(self):
        msg = self._ts.message(self._addr, socket.gethostbyname(socket.gethostname()), datetime.datetime.now())
        if msg is not None:
            try:
                self._socket.sendall(bytes(msg, 'UTF-8'))           # time to send the TimeStamp
                self._file.write(msg + '\n')                        # write the TimeStamp to file
            except ConnectionAbortedError:
                print('A Client has disconnected from:\t', self._addr)
                return -1
            except ConnectionResetError:
                print('A Client has forcibly disconnected from:\t', self._addr)
                return -1
        return 0

    """ Receive a TimeStamp, if it has been sent, without blocking the thread. """
    def _receive(self, buff_size=2048):
        try:
            msg = self._socket.recv(buff_size).decode()
            self._file.write(cmd.drop_commands_for_ts(msg) + '\n')
            if cmd.got_server(msg):                             # save the ip_addr:port of the client's server
                client_addr.append(cmd.parse(msg))
                client_thread.append(self)
            if cmd.wants_peers(msg):                            # send the list of peers for the client to connect
                self._socket.sendall(bytes(cmd.client_to_str(client_addr), 'UTF-8'))
        except socket.error:
            pass

    """ Override Thread.run() to send/receive messages through the socket. """
    def run(self, buff_size=2048):
        while True:
            if self._send() < 0:                                # keep sending TimeStamps?
                self.exit()
                return
            self._receive()                                     # get a TimeStamp

    """ Has this connection closed? """
    def test(self):
        try:
            self._socket.send(cmd.test)
        except:
            return True
        return False

    """ Close the connection and file. """
    def exit(self):
        self._socket.close()
        self._file.close()
예제 #2
0
class Client(threading.Thread):
    def __init__(self, id, host=cmd.host, port=cmd.port):
        threading.Thread.__init__(self)  # create a new thread
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._socket.connect((host, port))
        self._socket.setblocking(False)  # non-blocking mode
        self._host_ip = host
        self._my_ip = socket.gethostbyname(socket.gethostname())
        self._ts = TimeStamp(datetime.datetime.now())
        self._file = open(fname0 + str(id) + fname1,
                          'a')  # append to this file
        self._peer = PeerNetwork(id,
                                 self._file.name)  # has a listener for peers
        self._id = id
        self._me_str = 'Client ' + str(self._id) + ' '

    """ Send a TimeStamp, if it is time to do so. """

    def _send(self):
        msg = self._ts.message(self._my_ip, self._host_ip,
                               datetime.datetime.now())
        if msg is not None:
            self._socket.sendall(bytes(msg,
                                       'UTF-8'))  # time to send the TimeStamp
            self._file.write(msg + '\n')  # write to file

    """ Receive a TimeStamp, if it has been sent, without blocking the thread. """

    def _receive(self, buff_size=2048):
        try:
            msg = self._socket.recv(buff_size).decode()
            msg = cmd.clean(msg)
            self._file.write(msg + '\n')  # write to file
        except ConnectionAbortedError:
            print('Server has closed the connection.')
            self.exit()
        except ConnectionResetError:
            print('Server has forcibly closed the connection.')
            self.exit()
        except BlockingIOError:
            # print('The connection is waiting for I/O operation.')
            pass

    """ Send the server this Client's listener address. """

    def _invite_peers(self):
        self._socket.sendall(
            bytes(cmd.s_cmd + str(self.get_server_address()), 'UTF-8'))
        print(self._me_str, 'has listener socket at address',
              self.get_server_address())

    """ Connect to Peers in the network, and send the files. """

    def _connect_to_peers(self):
        peer_list = self._get_peers()
        print(self._me_str + str(peer_list) + '\t' + str(len(peer_list)))
        connected = False
        while not connected:  # attempt the connection to the full peer list
            try:
                self._peer.connect_and_send(peer_list)
                connected = True
            except ConnectionRefusedError:
                continue

    """ Get the list of peers from the server in a readable format. """

    def _get_peers(self, buff_size=2048):
        self._socket.sendall(bytes(cmd.g_cmd, 'UTF-8'))
        pl = ''
        while pl == '':  # get the list of Peers' listener addresses
            try:
                msg = self._socket.recv(buff_size).decode()
                pl, ts = cmd.get_pl_and_ts(msg)
                if ts != '':
                    self._file.write(
                        ts + '\n')  # write the TimeStamp to file, if any
            except:
                continue
        return pl  # convert the list to (host, port) tuples

    """ Override Thread.run() to send/receive messages through the socket. """

    def run(self):
        self._peer.start()  # tell the server this Client's listener address
        self._invite_peers()
        while not self._ts.finished(datetime.datetime.now()):
            self._receive()  # get a TimeStamp; exit on error
            self._send()  # send the TimeStamp
        print(self._me_str + 'finished exchanging TimeStamps with the Server.')
        self._connect_to_peers()
        print(self._me_str + 'finished sending TimeStamp file to Peers.')
        # self.exit()

    """ Close the connection and file. """

    def exit(self):
        self._peer.exit()
        self._socket.close()
        self._file.close()
        print(self._me_str, 'disconnected at', datetime.datetime.now())

    def get_server_address(self):
        return self._peer.get_host()