P2P网络:Python套接字未从其他节点接收数据

时间:2018-09-16 16:04:47

标签: python

我已经在线检查了文档和一些Stackoverflow帖子,但是无法调试我的代码。我认为我不正确地发送了字节,因此连接到套接字的其他节点无法“听到”调用。

使用sendall()是否有问题,或者打包字节串的方式有问题?

import logging
from random import randint
import socket
import sys
import time
import threading


class Server:

    connections = list()
    peers = list()

    def __init__(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('0.0.0.0', 10000))
        s.listen(1)
        logging.info('Successfully started the server on port 10000.')

        while True:
            c, a = s.accept()
            logging.info('New client node joins pool.')

            t = threading.Thread(target=self.handler, args=(c, a))
            t.daemon = True
            t.start()

            self.connections.append(c)
            self.peers.append(a[0])
            logging.info('New node connected: {}'.format(str(a[0])))
            self.send_peers()

    def handler(self, c, a):
        while True:
            data = c.recv(1024)

            logging.info('Sending data: {}'.format(data))

            for connection in self.connections:
                connection.sendall(data)

            if not data:
                logging.info('Node disconnected: {}:{}'.format(str(a[0]), str(a[1])))
                self.connections.remove(c)
                self.peers.remove(a[0])
                c.close()
                self.send_peers()
                break

    def send_peers(self):
        """Sends the list of peers in the swarm to all connected peers."""
        p = ''

        for peer in self.peers:
            p = p + peer + ','

        for connection in self.connections:
            connection.sendall(b'\x11' + p.encode())


class Client:
    def __init__(self, address):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.connect((address, 10000))
        logging.info('Successfully made a client connection at: {}. Listening..'.format(address))
        t = threading.Thread(target=self.send_message, args=(s,))
        t.daemon = True
        t.start()

        while True:
            data = s.recv(1024)
            print(data)

            if not data:
                break

            if data[0:1] == b'\x11':
                # Message prefixed with \x11, so we know it is a new node message
                self.update_peers(data[1:])
            else:
                # Since the message received isn't prefixed with \x11, we know it is a message
                logging.info('Received message: {}'.format(data.decode()))

    @staticmethod
    def send_message(s):
        """Sends a message to all connected nodes."""
        while True:
            message = str(input('Enter message: ')).encode()
            s.sendall(message)
            logging.info('Sending message: {}'.format(message.decode()))

    @staticmethod
    def update_peers(peer_data):
        """Refreshes the local copy of all connected nodes."""
        logging.info('Node dropped/connected. Updating connected peers list.')
        Tracker.peers = peer_data.decode.split(',')[:-1]


class Tracker:
    """Tracks the Peers connected within the swarm.

    This is a separate class due to data accessibility. We want to be able to access the peers list
    from outside the Client and Server classes.
    """
    peers = ['127.0.0.1']


if __name__ == '__main__':
    logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s',
                        level=logging.INFO,
                        datefmt='%Y-%m-%d %H:%M:%S')

    logging.info('Connecting..')

    while True:
        try:
            time.sleep(randint(1, 5))
            for peer in Tracker.peers:
                try:
                    server = Server()
                except KeyboardInterrupt:
                    sys.exit(0)
                except:
                    logging.warning('Server is already started. Becoming a client node.')

                try:
                    client = Client(peer)
                except KeyboardInterrupt:
                    sys.exit(0)
                except:
                    logging.warning('Could not become a client node.')
                    pass

        except KeyboardInterrupt:
            sys.exit(0)

0 个答案:

没有答案