[英]How to accept two connections using sockets in Python
I am working on a chat program. 我正在做一个聊天程序。 But right now it can only except one client.
但是目前只能有一个客户。 How would I make it to where it can accept two clients?
我要如何使其能够接受两个客户? I am still a bit of a noob when it comes to sockets so can you explain very thoroughly?
在套接字方面,我还是有点菜鸟的,所以您可以很详尽地解释一下吗?
Server Code: 服务器代码:
import socket
def mainFunc():
host = ""
port = 50000
ipList = []
nickNameList = []
num = True
s = socket.socket()
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
print("Connection from: " + str(addr) + "\n")
ipList.insert(0, str(addr))
while True:
data = c.recv(1024)
if not data:
break
if num == True:
nickNameList.insert(0, str(data))
num = False
else:
print("From " + nickNameList[0] + ": " + str(data) + "\n")
message = raw_input("Message you want to send: ")
print("\n")
c.send(message)
c.close()
I have tried changing the s.listen(1) to s.listen(2). 我尝试将s.listen(1)更改为s.listen(2)。 But that did not seem to allow a second person to connect.
但这似乎不允许第二个人进行联系。 Can someone explain why?
有人可以解释为什么吗?
One call to accept
accepts one connection. 一个
accept
呼叫将accept
一个连接。 To accept two connections, call accept
twice. 要接受两种连接方式,呼叫
accept
两次。
If you want two connections in sequence, but never more than one at a time, you just need a loop around the c, addr = s.accept()
and everything that follows it. 如果要顺序连接两个,但一次不超过一个,
c, addr = s.accept()
需要围绕c, addr = s.accept()
的循环c, addr = s.accept()
及其c, addr = s.accept()
所有内容。 Then it'll accept one connection, handle it until the socket closes and your break
executes, then handle the second connection, and so on. 然后它将接受一个连接,处理该连接,直到套接字关闭并执行
break
,然后处理第二个连接,依此类推。
In this case, the listen
backlog—the 2 in your s.listen(2)
—means it'll queue up no more than 2 waiting connections while you're processing the first one; 在这种情况下,
listen
积压(即s.listen(2)
在处理第一个连接时,它不会排队等待2个以上的等待连接。 anyone after that will get rejected. 之后的任何人都会被拒绝。
If you want two simultaneous connections, you have to do one of two things: 如果要同时进行两个连接,则必须执行以下两项操作之一:
gevent
, are basically the same idea.) gevent
是相同的想法。) asyncio
to simple loops around select
.) asyncio
到围绕select
简单循环)。) In this case, the listen
backlog is really only important if your program is too slow to keep up with connections as they come in. When that happens, it's usually better to refuse new connections than to accept them and slow things down even further, so keeping a small backlog is a good idea. 在这种情况下,仅当您的程序太慢而无法跟上进入连接的速度时,
listen
积压才真正重要。在这种情况下,拒绝新连接通常比接受新连接并进一步放慢速度要好,因此保持少量积压是一个好主意。
But since your connection handler blocks on raw_input
after each socket messages, this is going to be a weird design, to say the least. 但是由于您的连接处理程序会在每个套接字消息之后阻塞
raw_input
,至少可以这样说,这将是一个怪异的设计。 (Not the blocking part—you can fix that by assigning a thread, select
entry, coroutine, etc. to stdin. But what actually happens with the input. You've got 8 connections, and only 1 input. Which connection gets the result when the user types something?) (不是阻塞部分,您可以通过为stdin分配线程,
select
条目,协程等来解决此问题。但是输入实际上会发生什么。您只有8个连接,只有1个输入。哪个连接可以得到结果用户何时输入内容?)
Here's a simple threaded server: 这是一个简单的线程服务器:
def connection(c, addr):
while True:
# your existing while True loop
while True:
c, addr = s.accept()
t = threading.Thread(target=connection, args=(c, addr))
t.start()
However, for a realistic server that you want to be able to shut down in some way, you're going to want to provide some way to shut down the connection threads. 但是,对于您希望能够以某种方式关闭的现实服务器,您将需要提供某种方式来关闭连接线程。 Also, for servers that interact between clients (like sending one user's chat messages to all of the other users), you need some way to pass messages between the threads, or to share information between them.
同样,对于在客户端之间进行交互的服务器(例如向一个用户发送聊天消息给所有其他用户),您需要某种方式在线程之间传递消息或在线程之间共享信息。 Often you end up needing two threads per connection—one to block on
c.recv
, and another one to block on a queue and call c.send
with other users' messages. 通常,每个连接最终需要两个线程-一个线程在
c.recv
上c.recv
,另一个线程在队列上c.recv
,并与其他用户的消息一起调用c.send
。
For a multiplexing server, the different approaches look very different, but there are good examples for all of them. 对于多路复用服务器,不同的方法看起来非常不同,但是所有方法都有很好的示例。 See
asyncio
, selectors
for their examples, Socket Programming HOWTO for the select
examples, and Google for examples for third-party libraries like Twisted, gevent, etc. 见
asyncio
, selectors
了他们的榜样, Socket编程HOWTO的select
的例子,而谷歌对于像扭曲,GEVENT等第三方库的例子
As a side note, you seem to be expecting that send
is guaranteed to send an entire message in one go, and that the other side's recv
will receive that entire message and nothing else. 附带说明一下,您似乎希望
send
肯定能一次发送完整的消息,而另一端的recv
将接收到整个消息,而不会收到其他任何消息。 TCP guarantees no such thing. TCP不能保证没有这种事情。 See Sockets are byte streams, not message streams for more details.
有关更多详细信息,请参见套接字是字节流,而不是消息流 。
Also, in nickNameList.insert(0, str(data))
, what is the str
for? 另外,在
nickNameList.insert(0, str(data))
, str
是什么? In Python 2.x, data
is already a str
, so this just wastefully makes an extra copy for no good reason. 在Python 2.x中,
data
已经是一个str
,因此这没有充分的理由浪费了额外的副本。 In Python 3.x, data
is a bytes
, so this converts that into its string representation, like "b'0Cool'"
instead of "0Cool"
, which is almost certainly not what you want. 在Python 3.x中,
data
是一个bytes
,因此这会将其转换为字符串表示形式,例如"b'0Cool'"
而不是"0Cool"
,这几乎肯定不是您想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.