- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在编写一个 Python (v3.7.3) 套接字服务器,我想为其使用阻塞 I/O。我使用 select()
没有超时来接受新客户以及从他们那里读取。我可以关闭监听套接字以中止 select(),并捕获 OSError 作为停止执行的指示。
但是,这在单独的线程中运行时似乎不起作用,我不明白为什么。
我知道还有其他方法可以完成此操作,例如使用超时、为 select() 使用虚拟套接字,或者与监听器建立虚拟连接以将其唤醒。但是这些都在某种程度上违背了使用 select() 的目的,并且在单线程中运行时不是必需的。
这是重现问题的基本示例,在我的实际代码中,它只代表许多线程中的一个(因此,我首先使用线程):
#!/usr/bin/env python3
import signal
import socket
import threading
class SocketCloseTest:
"""Simple test case for using socket.close() to abort select.select()"""
def __init__(self, port, address=None):
self.port = port
self.address = address or ''
self.socket = None
def stop(self):
"""Close listening socket to stop select.select()"""
if self.socket:
print("Closing listener", self.socket)
self.socket.close()
print("Listener closed", self.socket)
def threaded_run(self):
"""Run test in a separate thread"""
thread = threading.Thread(target=self.run)
print("Starting sub-thread")
thread.start()
thread.join()
print("Sub-thread ended")
def run(self):
"""Run test"""
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Reuse port for quick re-launch of the application
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind((self.address, self.port))
print("Starting listener")
self.socket.listen()
try:
print("select() started")
r, w, e = select.select([self.socket], [], [])
except OSError:
print("select() aborted")
else:
print("select() completed")
if __name__ == '__main__':
tester = SocketCloseTest(5000, address='')
# Set up signal handler for Ctrl-C
def signal_handler(signum, frame):
print("Received signal {}".format(signum))
tester.stop()
signal.signal(signal.SIGINT, signal_handler)
# This works
tester.run()
# This doesn't work
# tester.threaded_run()
print("Main thread ended")
当使用 test.run()
时,它按预期运行并产生以下结果:
Starting listener
Select started
^CReceived signal 2
Closing listener <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 5000)>
Listener closed <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
Select cancelled
Main thread ended
但是,当使用 tester.threaded_run()
运行时,它只是卡在对 select() 的调用应该中止的位置。奇怪的是,此时将作业置于后台会导致代码继续执行:
Starting sub-thread
Starting listener
Select started
^CReceived signal 2
Closing listener <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 5000)>
Listener closed <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
--Ctrl-Z pressed here to suspend job in shell--$ bg
--Shell reports job in background--
Select cancelled
Sub-thread ended
Main thread ended
谢谢...
accept()
有完全相同的症状。最佳答案
close()
在多线程情况下不会执行您想要的操作。请改用您描述的其他机制之一。
在单线程情况下,控制权返回到 select()
,它会重新启动并注意到现在已关闭的文件描述符上的 EBADF。 (当然,这是非常危险的,因为 fd #3 可能随时被任何其他线程甚至复杂的信号处理程序回收,尽管您的玩具程序看起来很安全。)在多线程情况下, close()
不会唤醒您的 select()
ing 线程。
Note:
close()
releases the resource associated with a connection but does not necessarily close the connection immediately. If you want to close the connection in a timely fashion, callshutdown()
beforeclose()
.
其实这是一个比较棘手的和平台相关的问题。摘录 2008 article in the venerable Dr Dobb's :
On some operating systems, [ shutdown() instead of close() ] is also the only working solution: On FreeBSD, a close() without shutdown() does not wake up the processes waiting in a read() or select()....
Another issue to consider is that closing by shutdown() or by close() may not be considered a read event in the OS....
However, shutdown() works only on the sockets with established connections, not on the ones listening for new connections nor on the other kinds of file descriptors....
(就其值(value)而言,在我的系统上,shutdown()
确实唤醒了 select()
ing 线程。)
关于python - 无法关闭监听套接字以从单独的线程中止 accept()/select(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58827001/
我正在维护一些 Java 代码,我目前正在将它们转换为 C#。 Java 代码是这样做的: sendString(somedata + '\000'); 在 C# 中,我正在尝试做同样的事情: sen
如何确定函数中传递的参数是字符串还是字符(不确定如何正确调用它)文字? 我的函数(不正确): void check(const char* str) { // some code here }
我真的不知道如何准确地提出这个问题,但我希望标题已经说明了这一点。 我正在寻找一种方法(一个框架/库),它提供了执行 String.contains() 函数的能力,该函数告诉我给定的字符串是否与搜索
我正在尝试编写一些读取 Lambda 表达式并输出 beta 缩减版本的东西。 Lambda 的类型如下:\variable -> expression,应用程序的形式为 (表达式) (表达式)。因此
StackOverflow 上的第 1 篇文章,如果我没能把它做好,我深表歉意。我陷入了一个愚蠢的练习,我需要制作一个“刽子手游戏”,我尝试从“.txt”文件中读取单词,然后我得到了我的加密函数,它将
我想在 Groovy 中测试我的 Java 自定义注释,但由于字符问题而未能成功。 Groovyc: Expected 'a' to be an inline constant of type cha
当我尝试在单击按钮期间运行 javascript location.href 时,出现以下错误“字 rune 字中的字符过多”。 最佳答案 这应该使用 OnClientClick相反? 您可能还想停
我想要类似的东西: let a = ["v".utf8[0], 1, 2] 我想到的最接近的是: let a = [0x76, 1, 2] 和 "v".data(using: String.Encod
有没有办法在 MySQL 中指定 Unicode 字 rune 字? 我想用 Ascii 字符替换 Unicode 字符,如下所示: Update MyTbl Set MyFld = Replace(
阅读 PNG 规范后,我有点惊讶。我读过字 rune 字应该用像 0x41 这样的二进制值进行硬编码,而不是在(程序员友好的)'A' 中。问题似乎是在具有不同底层字符集的不同系统上编译期间字 rune
考虑一个具有 UTF-8 执行字符集的 C++11 编译器(并且符合要求 char 类型为有符号 8 位字节的 x86-64 ABI) . 字母 Ä(元音变音)具有 0xC4 的 unicode 代码
为什么即使有 UTF-8 字符串文字,C11 或 C++11 中也没有 UTF-8 字 rune 字?我知道,一般来说,字 rune 字表示单个 ASCII 字符,它与单字节 UTF-8 代码点相同,
我怎样才能用 Jade 做到这一点? how would I do this 我几乎可以做任何事情,除了引入一个 span 中间句子。 最佳答案 h3.blur. how would I do t
这似乎是一个非常简单的问题,但我只是想澄清我的疑问。我正在查看其他开发人员编写的代码。有一些涉及 float 的计算。 示例:Float fNotAvlbl = new Float(-99); 他为什
我想知道第 3 行“if dec:”中的“dec”是什么意思 1 def dec2bin(dec): 2 result='' 3 if dec:
我试图在字符串中查找不包含任何“a”字符的单词。我写了下面的代码,但它不起作用。我怎么能对正则表达式说“不包括”?我不能用“^”符号表示“不是”吗? import re string2 = "asfd
这个问题在这里已经有了答案: Is floating point math broken? (31 个答案) Is floating point arbitrary precision availa
我正在创建一个时尚的文本应用程序,但在某些地方出现错误(“字 rune 字中的字符太多”)。我只写了一个字母,但是当我粘贴它时,它会转换成许多这样的字母:“\uD83C\uDD89”,原始字母是“🆉
我正在尝试检查用户是否在文本框中输入了一个数字值,是否接受了小数位。非常感谢任何帮助。 Private Sub textbox1_AfterUpdate() If IsNumeric(textbox1
我知道一个 Byte 是 8 位,但其他的代表什么?我正在参加一个使用摩托罗拉 68k 架构的汇编类(class),我对目前的词汇感到困惑。 最佳答案 如 operator's manual for
我是一名优秀的程序员,十分优秀!