Beispiel #1
0
 def __init__(self, name, addr, peers):
     self._name = name
     self._peers = peers
     self._comm = Communicator(name, addr)
     self._last_received = dict(
     )  # словарь для номеров последнего полученного сообщения от каждого отправителя
     self._seq_no = 0  # Sequence Number для последнего отправленного сообщения
     self._received = set()  # множество всех полученных сообщений
     self._hold_back_queue = dict(
     )  # очередь сообщений для реализации порядка
Beispiel #2
0
class PingServer:
    def __init__(self, name, addr):
        self._comm = Communicator(name, addr)

    def run(self):
        while True:
            req = self._comm.recv()

            # process PING request
            if req.type == 'PING':
                resp = Message('PONG', req.body)
                self._comm.send(resp, req.sender)

            # unknown request
            else:
                err = Message('ERROR', 'unknown request type: %s' % req.type)
                self._comm.send(err, req.sender)
Beispiel #3
0
class RpcClient:
    """This is client-side RPC implementation"""

    def __init__(self, server_addr):
        self._comm = Communicator('client')
        self._server_addr = server_addr

    def call(self, func, *args):
        """Call function on RPC server and return result"""

        packet = list()
        packet.append(func)
        packet.extend(args)                                   # Упаковываем всё в json и помещяем в body сообщения
        msg = Message('REQUEST', body=json.dumps(packet), sender=self._comm._addr)

        if func == 'append':                                  # Для append'а никаких retry'ев, так как неидемпотентен
            self._comm.send(msg, self._server_addr)
            resp = self._comm.recv(1)
            if resp is None:
                raise Exception("Response timeout")
            elif resp.type == 'ERROR':
                raise Exception(resp.body)
            else:
                return resp.body
        else:
            while True:                                        # для идемпотентных отправялем запросы пока не получим ответ
                self._comm.send(msg, self._server_addr)
                resp = self._comm.recv(timeout=1)
                if resp is None:
                    continue
                elif resp.type == 'ERROR':
                    raise Exception(resp.body)
                else:
                    return resp.body
Beispiel #4
0
class Peer:
    def __init__(self, name, addr, peers):
        self._name = name
        self._peers = peers
        self._comm = Communicator(name, addr)
    
    def run(self):
        while True:
            msg = self._comm.recv()

            # local user wants to send a message to the chat
            if msg.type == 'SEND' and msg.is_local():
                # basic broadcast
                bcast_msg = Message('BCAST', msg.body, {'from': self._name})
                for peer in self._peers:
                    self._comm.send(bcast_msg, peer)

            # received broadcasted message
            elif msg.type == 'BCAST':
                # deliver message to the local user
                deliver_msg = Message('DELIVER', msg.headers['from'] + ': ' + msg.body)
                self._comm.send_local(deliver_msg)
Beispiel #5
0
class PingClient:
    def __init__(self, name, server_addr):
        self._comm = Communicator(name)
        self._server_addr = server_addr

    def run(self):
        while True:
            command = self._comm.recv_local()

            # send PING to server
            if command.type == 'PING':
                self._comm.send(command, self._server_addr)
                resp = self._comm.recv(timeout=1)
                if resp is not None and resp.type == 'PONG':
                    self._comm.send_local(resp)
                else:
                    err = Message('ERROR', 'No reply from the server')
                    self._comm.send_local(err)

            # unknown command
            else:
                err = Message('ERROR', 'unknown command: %s' % command.type)
                self._comm.send_local(err)
Beispiel #6
0
class Receiver:
    def __init__(self, name, addr):
        self._comm = Communicator(name, addr)

    def run(self):
        while True:
            msg = self._comm.recv()

            # deliver INFO-1 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all that were recieved but at most once
            if msg.type == 'INFO-1':
                pass

            # deliver INFO-2 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all at least once
            elif msg.type == 'INFO-2':
                pass

            # deliver INFO-3 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all exactly once
            elif msg.type == 'INFO-3':
                pass

            # deliver INFO-4 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all exactly once in the order
            elif msg.type == 'INFO-4':
                pass

            # unknown message
            else:
                err = Message('ERROR', 'unknown message type: %s' % msg.type)
                self._comm.send(err, msg.sender)
Beispiel #7
0
class Receiver:
    def __init__(self, name, addr):
        self._comm = Communicator(name, addr)
        self._received_msgs = set()                         # множество уже полученных сообщений

    def run(self):
        while True:
            msg = self._comm.recv()

            # deliver INFO-1 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all that were recieved but at most once
            if msg.type == 'INFO-1':
                if msg not in self._received_msgs:
                    self._comm.send_local(msg)
                    self._received_msgs.add(msg)                    # добавляем полученное сообщение
                                                                    # в множество уже полученных сообщений
                                                                    # чтобы не отправить одно сообщение дважды

            # deliver INFO-2 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all at least once
            elif msg.type == 'INFO-2':
                self._comm.send_local(msg)                           # а здесь можем отправлять сообщения сколь угодно
                self._comm.send(msg, msg._sender)

            # deliver INFO-3 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all exactly once
            elif msg.type == 'INFO-3':
                if msg not in self._received_msgs:
                    self._comm.send_local(msg)
                    self._received_msgs.add(msg)
                self._comm.send(msg, msg._sender)                      # здесь нам важно отправить ответ sender'у

            # deliver INFO-4 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all exactly once in the order
            elif msg.type == 'INFO-4':
                if msg not in self._received_msgs:
                    self._comm.send_local(msg)
                    self._received_msgs.add(msg)
                self._comm.send(msg, msg._sender)                      # здесь нам важно отправить ответ sender'у

            # unknown message
            else:
                err = Message('ERROR', 'unknown message type: %s' % msg.type)
                self._comm.send(err, msg.sender)
Beispiel #8
0
 def __init__(self, name, addr):
     self._comm = Communicator(name, addr)
     self._received_msgs = set()                         # множество уже полученных сообщений
Beispiel #9
0
 def __init__(self, name, server_addr):
     self._comm = Communicator(name)
     self._server_addr = server_addr
Beispiel #10
0
class Sender:
    def __init__(self, name, recv_addr):
        self._comm = Communicator(name)
        self._recv_addr = recv_addr
        self._local_messages = collections.deque(
        )  # очередь локальных сообщений

    def run(self):
        while True:
            try:  # берём очередное локальное сообщение
                msg = self._local_messages.popleft()
            except IndexError:
                msg = self._comm.recv_local()

            # deliver INFO-1 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all that were recieved but at most once
            if msg.type == 'INFO-1':
                self._comm.send(msg, self._recv_addr)  # просто отправляем

            # deliver INFO-2 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all at least once
            elif msg.type == 'INFO-2':
                while True:  # отправляем и ждём ответ;
                    self._comm.send(
                        msg, self._recv_addr
                    )  # если ответ - сообщение с локального сервера,
                    resp = self._comm.recv(
                        timeout=0.5
                    )  # то добавляем его в очередь и дальше ждём ответ
                    if resp is None:  # от receiver'а (с повторной отправкой)
                        continue
                    elif resp.is_local():
                        self._local_messages.append(resp)
                    else:
                        resp._sender = msg._sender
                        if resp == msg:
                            break

            # deliver INFO-3 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all exactly once
            elif msg.type == 'INFO-3':
                while True:  # для INFO-3 логика такая же, как для INFO-2,
                    self._comm.send(
                        msg,
                        self._recv_addr)  # отличия есть только у receiver'a
                    resp = self._comm.recv(timeout=0.5)
                    if resp is None:
                        continue
                    elif resp.is_local():
                        self._local_messages.append(resp)
                    else:
                        resp._sender = msg._sender
                        if resp == msg:
                            break

            # deliver INFO-4 message to receiver user
            # underlying transport: unreliable with possible repetitions
            # goal: receiver knows all exactly once in the order
            elif msg.type == 'INFO-4':
                while True:  # для INFO-4 логика такая же, как для INFO-2,
                    self._comm.send(
                        msg,
                        self._recv_addr)  # отличия есть только у receiver'a
                    resp = self._comm.recv(timeout=0.5)
                    if resp is None:
                        continue
                    elif resp.is_local(
                    ):  # порядок сохраняется потому, что новые
                        self._local_messages.append(
                            resp
                        )  # локальные сообщения мы не отправляем до тех пор
                    else:  # пока не получим ответ от receiver'а
                        resp._sender = msg._sender
                        if resp == msg:
                            break

            else:
                err = Message('ERROR', 'unknown command: %s' % msg.type)
                self._comm.send_local(err)
Beispiel #11
0
 def __init__(self, name, recv_addr):
     self._comm = Communicator(name)
     self._recv_addr = recv_addr
     self._local_messages = collections.deque(
     )  # очередь локальных сообщений
Beispiel #12
0
 def __init__(self, server_addr):
     self._comm = Communicator('client')
     self._server_addr = server_addr
Beispiel #13
0
 def __init__(self, name, addr, peers):
     self._name = name
     self._peers = peers
     self._comm = Communicator(name, addr)
Beispiel #14
0
 def __init__(self, name, recv_addr):
     self._comm = Communicator(name)
     self._recv_addr = recv_addr
Beispiel #15
0
 def __init__(self, server_addr):
     self._comm = Communicator('client')
     # Your implementation
     pass
Beispiel #16
0
 def __init__(self, name, addr):
     self._comm = Communicator(name, addr)
Beispiel #17
0
class Peer:
    def __init__(self, name, addr, peers):
        self._name = name
        self._peers = peers
        self._comm = Communicator(name, addr)
        self._last_received = dict(
        )  # словарь для номеров последнего полученного сообщения от каждого отправителя
        self._seq_no = 0  # Sequence Number для последнего отправленного сообщения
        self._received = set()  # множество всех полученных сообщений
        self._hold_back_queue = dict(
        )  # очередь сообщений для реализации порядка

    def run(self):
        while True:
            msg = self._comm.recv()

            # local user wants to send a message to the chat
            if msg.type == 'SEND' and msg.is_local():
                # basic broadcast
                self._seq_no += 1
                bcast_msg = Message(
                    'BCAST', msg.body, {
                        'from': self._name,
                        'seq_no': self._seq_no,
                        'sender': self._name
                    })  # будем добавлять имя процесса,
                # который отправил сообщение
                for peer in self._peers:
                    self._comm.send(bcast_msg, peer)

            # received broadcasted message
            elif msg.type == 'BCAST':
                # deliver message to the local user

                # если сообщение уже обработали, то снова обрабатывать его не будем
                if (msg.body not in self._received) and (msg.headers['sender']
                                                         != self._name):
                    self._received.add(msg.body)

                    if msg.headers['from'] != self._name:
                        msg.headers['sender'] = self._name
                        for peer in self._peers:  # после получения сообщения отправим его всем другим
                            self._comm.send(msg, peer)

                    # проверка порядка
                    if msg.headers['seq_no'] == (
                            self._last_received.setdefault(
                                msg.headers['from'], 0) + 1):

                        deliver_msg = Message(
                            'DELIVER', msg.headers['from'] + ': ' + msg.body)
                        self._comm.send_local(deliver_msg)
                        self._last_received[msg.headers['from']] += 1

                        # чистим очередь
                        while self._hold_back_queue.setdefault(
                                msg.headers['from'], list()):
                            if self._hold_back_queue[msg.headers['from']][0][0] == \
                                    (self._last_received[msg.headers['from']] + 1):

                                # отправляем сообщения из очереди последовательно (по порядку)
                                next_msg = (heapq.heappop(
                                    self._hold_back_queue[msg.headers['from']])
                                            )[1]
                                deliver_msg = Message(
                                    'DELIVER', next_msg.headers['from'] +
                                    ': ' + next_msg.body)
                                self._comm.send_local(deliver_msg)
                                self._last_received[msg.headers['from']] += 1

                            else:  # если в очереди нет следующего сообщения, ничего не делаем
                                break

                    # если N-ое сообщение пришло быстрее, чем предыдущее, то не обрабатываем его, а добавляем в очередь
                    elif msg.headers['seq_no'] > (
                            self._last_received.setdefault(
                                msg.headers['from'], 0) + 1):
                        heapq.heappush(
                            self._hold_back_queue.setdefault(
                                msg.headers['from'], list()),
                            tuple((msg.headers['seq_no'], msg)))