问题
I'm sort of new to python and this is the first time I'm using sockets, I am trying to make an application that has a client and server, A user can type into the client and it will be sent to the server which then sends it to all the other clients. I have it to a working state but whenever I try to send a second message I always get an error 'error: [Errno 10058] A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call'. How can I make this work?
Tried adding a socket shutdown and close before going starting a new socket or sending a new message, Tried just using the existing socket again and neither work giving me No error but the program just hangs while sending to the server.
Server
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__()
Client
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__()
回答1:
Your server calls __listen__()
and thereby accept()
recursively each time after it did sendto()
a client, i. e. it waits for a new connection after each message sent - that cannot work.
The server has to wait simultaneously for connections and data from clients; this is easy with select.select(). Replace your __init__()
, __broadcast__()
and __listen__()
with
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)
The client has a similar problem of not simultaneously waiting for socket and terminal input. For a working client implementation, see this answer to Handle multiple requests with select.
来源:https://stackoverflow.com/questions/57964690/python-chat-client-server-sockets-issue