【发布时间】:2020-07-19 01:26:29
【问题描述】:
所以在有人说它重复之前,我已经看到了多个与该错误有关的问题,但没有注意到其中任何一个与我的问题相同。
我正在尝试制作一个小项目,包括 SSL 上的套接字,并且在尝试捕获用户是否尝试连接原始套接字而不是 ssl 包装的套接字(这会引发 ConnectionResetError)时,我得到了一个不同的错误.
我的代码:
import socket
from classes import ClientThread
import ssl
from time import sleep
server = 'localhost'
port = 12345
threads = []
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain(certfile="cert.pem", keyfile="cert.pem")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((server, port))
print(f"[*] server started, listening on port {port}")
while True:
s.listen()
with context.wrap_socket(s, server_side=True) as ssock:
try:
conn, addr = ssock.accept()
client = ClientThread(conn=conn, ip=addr[0], port=addr[1])
client.start()
threads.append(client)
print(f'Threads running: {len(threads)}')
except ConnectionResetError:
print(f'Could not establish ssl handshake with a client.')
我得到的错误是:
Traceback (most recent call last):
File "C:/Users/x/x/server.py", line 17, in <module>
s.listen()
OSError: [WinError 10038] An operation was attempted on something that is not a socket
我尝试在异常之后设置一些睡眠时间,也许它需要重置套接字但没有帮助,尝试使用 While True 的位置进行一些操作,并且在重置整个套接字帮助时,我不想重置所有我的客户端线程只是因为客户端没有尝试使用 SSL 套接字登录。
我认为它与 wrap_socket 有关,因为它修改了传递给它的套接字实例,但找不到解包的方法。
提前谢谢你!
【问题讨论】:
-
你应该只在循环外调用一次listen。
-
@tdelaney 感谢您的回复,但它只会接受一个连接,而不是多线程服务器。
-
不,listen 只是使套接字能够接受传入的连接请求,并限制这些请求中有多少可以积压在 TCP 堆栈中而尚未被接受。
accept等待连接进来。你听一次并接受很多次。在linux上可以(但不正常)多次调用listen。我假设 Windows 或 ssl 的东西使事情有所不同,但无法测试。 -
值得将监听移到一段时间之外看看会发生什么。
-
我没有看到这个问题的好副本,所以我提供了我的评论作为答案。顺便说一句,感谢堆栈跟踪,它可以很容易地发现问题行。令人惊讶的是有多少人不这样做。