简单socket服务器的基本理解
Posted
技术标签:
【中文标题】简单socket服务器的基本理解【英文标题】:basic understanding of simple socket server 【发布时间】:2017-01-25 06:51:48 【问题描述】:我是套接字编程的新手,正在尝试了解套接字的工作原理。目前我正在尝试使用 python 套接字库来查看它是如何工作的。
现在有些事情我无法理解。 让我们举一个例子,如here 所示,使用 Python 套接字库用 Python 编写的简单回显客户端和服务器。
echo 服务器如下所示 # echo_server.py 导入套接字
host = '' # Symbolic name meaning all available interfaces
port = 12345 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
echo 客户端如下所示
# echo_client.py
import socket
host = socket.gethostname()
port = 12345 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))
我的问题
-
在 echo_server.py 中,当我说 conn 时,addr = s.accept(), accept() 做了两件事。 1. 它返回连接客户端的地址(ip 和端口),存储在 addr 和 2. 它创建一个新的套接字(称为客户端套接字),可以在这里使用 conn 引用,用于与连接的客户端交互。
再次在 echo_server.py 中,s.listen(1) 建议最多允许 1 个积压,我似乎仅从理论上理解它是服务器希望允许继续等待的最大客户端数当服务器忙于处理已经连接的客户端时,在队列中。现在,当另一个客户端也连接到此服务器时会发生什么? conn 和 addr 变量是否会被新值覆盖?或者如何处理?
有没有一些简单实用的例子来演示这个?
【问题讨论】:
【参考方案1】:现在,当另一个客户端也连接到此服务器时会发生什么? conn 和 addr 变量是否会被新值覆盖?或者如何处理?
在您的示例中,不会发生任何有趣的事情。连接尝试将挂起。对connect()
的每个客户端调用都必须与对accept()
的服务器调用相匹配。由于您只调用了一次accept()
,因此最多只能连接一个客户端。
如果您希望能够连续接受来自后续客户端的连接,请尝试以下操作:
import socket
host = '' # Symbolic name meaning all available interfaces
port = 12345 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
while True:
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
如果您希望能够并行接受来自客户端的连接,即。同时来自多个客户,那么您还有更多工作要做。但这不是你今天的问题的一部分。
【讨论】:
是的,了解如何将 s.accept() 放置在其中同时使服务器接受多个连接,可能不是并行的,而是随后以串行的方式,这又是有道理的。但是,那有什么好处呢?我的意思是它与将 s.accept() 放在外面并让一个客户端单独连接它是不一样的。是不是在这段时间里,积压的概念就出现了?如果是的话,是否有一个例子证明它会非常感激。另外,每个 accept() 的 conn 和添加变量怎么样?它会被每个客户覆盖吗? 记住,s.accept() 是对监听套接字“s”的阻塞调用。当客户端“连接”到侦听套接字时,会创建一个新套接字,并将其传递回变量/引用“conn”。引用“conn”和“addr”将在每次额外调用 s.accept() 时获得新值,就像任何该形式的 python 函数调用一样。我会假设积压允许在拒绝传入请求之前等待接受的传入连接请求的数量。【参考方案2】:现在,当另一个客户端也连接到此服务器时会发生什么? conn 和 addr 变量是否会被新值覆盖?或者如何处理?
正如 Rob 在另一个答案中所指出的,您的代码将只接受一个客户端。对于来自客户端的任何连接请求,必须调用 accept
。并相应地编码。现在回答您的问题,是的, (conn,addr) 对将被覆盖。在再次调用accept
以建立新连接之前,代码应负责将它们传递给某个连接线程。
有一些简单的实际例子来演示这个吗?有一些简单的实际例子来演示这个吗?
在接受多个客户端的更新代码中,尝试在几次连接后不要调用accept
,并注意TCP 连接状态表(例如netstat
)以查看不同积压值的行为。
【讨论】:
以上是关于简单socket服务器的基本理解的主要内容,如果未能解决你的问题,请参考以下文章