我已经在线检查了文档和一些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)