问题描述
server.py
import socket, select, signal, errno, os, sys
from threading import Thread
def broadcast_data (sock, message):
for socket in CONNECTION_LIST:
#use:
#if socket != s and socket != sock:
#if you want to broadcast to all but sending client and server
# print sock.getpeername()[1]
# print CLIENT_LIST[0][1]
if socket != s:
try :
socket.send(message)
except :
#broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
CONNECTION_LIST.remove(socket)
def handle_cli():
#process client data
data = sock.recv(RECV_BUFFER)
if data == '?':
broadcast_data(sock, hand_cl(CLIENT_LIST))
elif data == 'removeme':
hold = rem_cl(sock.getpeername()[1],CLIENT_LIST)
CLIENT_LIST = hold
elif data:
broadcast_data(sock, "\r" + '<' + str(sock.getpeername()) + '> ' + data)
else:
sock.close()
CONNECTION_LIST.remove(sock)
def hand_inter(signum, frame):
print hand_cl(CLIENT_LIST)
def hand_qui(signum, frame):
sys.exit(0)
def hand_cl(cl):
totstring = "Current clients connected:"
for c in cl:
totstring+= " "+str(c)
totstring+="\n"
return totstring
def rem_cl(peername,cl):
cl = [(ip, port) for ip, port in cl if port != peername]
return cl
if __name__ == "__main__":
#keep track of socket descriptors
signal.signal(signal.SIGINT, hand_inter)
signal.signal(signal.SIGQUIT, hand_qui)
CONNECTION_LIST = []
CLIENT_LIST = []
RECV_BUFFER = 4096
HOST = 'localhost'
PORT = int(sys.argv[1])
ADDR = (HOST, PORT)
if len(sys.argv) > 2:
MAXHOST = int(sys.argv[2])
else:
MAXHOST = 2
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(ADDR)
s.listen(MAXHOST)
#add server socket to the list of readable connections
CONNECTION_LIST.append(s)
print "Chat server started on port " + str(PORT)
while 1:
#fix for signal interrupt
while True:
try:
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])
except select.error, v:
if v[0] != errno.EINTR: raise
else: break
for sock in read_sockets:
#if sock in read socks == new s, new connection
if sock == s:
sockfd, addr = s.accept()
conmax = [MAXHOST, len(CONNECTION_LIST)]
conmax = str(conmax)
#send maxhost number for comparison
sockfd.send(conmax)
CONNECTION_LIST.append(sockfd)
CLIENT_LIST.append(addr)
print "Client (%s, %s) connected" % addr
broadcast_data(sockfd, "[%s:%s] entered room\n" % addr)
#else it's a message from a pre-connected client
else:
Thread(target=handle_cli).start()
s.close()
目标:每当客户端发送消息“ removeme”时,我都希望CLIENT_LIST从CLIENT_LIST中删除特定的客户端。 方法rem_cl可以正常工作并返回正确的结果,但是当我尝试将CLIENT_LIST重新分配给新的更新列表时,出现错误:
line 26, in handle_cli
hold = rem_cl(sock.getpeername()[1],CLIENT_LIST)
UnboundLocalError: local variable 'CLIENT_LIST' referenced before assignment
但是,如果删除CLIENT_LIST = hold
不会出现任何错误。
如何将CLIENT_LIST重新分配为此新返回的列表?
1楼
在函数handle_cli()
,当您尝试将值分配给CLIENT_LIST
,您正在将其分配给局部变量(而不是全局变量)。
为了将该值分配给您在脚本中使用的全局变量CLIENT_LIST
,必须首先使用global
语句:
global CLIENT_LIST
CLIENT_LIST = ...
: 如果没有global
不可能分配给global变量 。
另外, 在python中检查使用“ global”关键字的问题 。