python - Python 聊天客户端和服务器套接字问题
问题描述
我对python有点陌生,这是我第一次使用套接字,我正在尝试制作一个具有客户端和服务器的应用程序,用户可以输入客户端并将其发送到服务器然后将其发送给所有其他客户端。我让它处于工作状态,但每当我尝试发送第二条消息时,我总是收到一个错误'错误:[Errno 10058] 不允许发送或接收数据的请求,因为套接字已经在那个方向关闭了之前的关机通话”。我怎样才能使这项工作?
尝试在开始新套接字或发送新消息之前添加套接字关闭和关闭,再次尝试仅使用现有套接字,但都没有工作给我没有错误,但程序只是在发送到服务器时挂起。
服务器
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __init__():
HOST = '0.0.0.0'
PORT = 50012
print("Initialising..")
print("Initialized.")
print("Binding..")
s.bind((HOST, PORT))
print("Bound.")
print("Listener started")
__listen__(HOST, PORT)
def __broadcast__(list_clients, conn, addr, HOST, PORT):
print("broadcasting")
while 1:
data = conn.recv(1024)
if not data: break
print "{} Recieved from {}".format(data, addr)
for x in list_clients:
conn.sendto(data, x)
__listen__(HOST, PORT)
def __listen__(HOST, PORT):
print("listening")
s.listen(1)
conn, addr = s.accept()
list_clients=[]
list_clients.append(addr)
print 'Connected by', addr
__broadcast__(list_clients, conn, addr, HOST, PORT)
def ext():
conn.close()
def __main__():
print("Initialising..")
__init__()
print("Initialized.")
print("Listener starting..")
__listen__()
__init__()
客户
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def __init__():
HOST = '127.0.0.1'
PORT = 50012
__connect__(HOST, PORT)
def __connect__(HOST, PORT):
s.connect((HOST, PORT))
__sendmessage__(HOST, PORT)
def __sendmessage__(HOST, PORT):
s.sendall(raw_input("You $: "))
while 1:
data = s.recv(1024)
print data
__sendmessage__(HOST, PORT)
def __exit__():
s.shutdown(0)
__init__()
解决方案
您的服务器在每次执行客户端后都会调用__listen__()
并因此递归,即它在发送每条消息后等待新连接 - 这是行不通的。服务器必须同时等待来自客户端的连接和数据;这很容易。替换你的,和accept()
sendto()
select.select()
__init__()
__broadcast__()
__listen__()
from select import select
HOST = '0.0.0.0'
PORT = 50012
s.bind((HOST, PORT))
s.listen(1)
list_clients = []
for reads in iter(lambda: select([s]+list_clients, [], [])[0], []):
for ready in reads: # each time select reports something is ready
if s == ready: # accept new client if it's the server socket
conn, addr = s.accept()
list_clients.append(conn) # store the connection socket
print 'connected by', addr
else: # data from a client
try: data = ready.recv(1024)
except socket.error: data = ''
if not data: # client disconnected, remove
list_clients.remove(ready)
ready.close()
continue
print "{} received from {}".format(data, ready.getpeername())
print("broadcasting")
for x in list_clients: x.send(data)
客户端有一个类似的问题,即不能同时等待套接字和终端输入。对于有效的客户端实现,请参阅使用 select 处理多个请求的答案。
推荐阅读
- php - Laravel 5.6 - 在日志/laravel.log ubuntu xenial 16.04 上的权限被拒绝
- eclipse - eclipse - 无法将选定的文本解析为定义的函数或成员
- java - Java 等效于 Kotlin 中的 arrayof()/listof()/setof()/mapof()
- class - 在 drupal 8 的标题区域添加自定义类
- asp.net-mvc - 使用实体属性进行数据验证
- c# - c#:如何自动更新服务?
- javascript - d3拖动功能返回错误
- c++ - CMake:如何清除目标编译选项
- c# - 条目显示和隐藏密码
- reactjs - 在 Office-ui-Fabric - ReactJS 中的 DetailsLists 组件的同一行上添加一个 EDIT 按钮