这是一个非常意外的行为:
这是经典的教科书简短程序,它使用一个线程从套接字流中一个接一个地获取字符并显示它,并使用第二个线程读取输入并通过相同的套接字流发送输入。
导入套接字 导入线程 进口机 导入系统
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
def rxWorker():
while(True):
r = s.recv(1)
print(r.decode('ascii'), end='')
def txWorker():
while (True):
i = input('')
s.send(i.encode())
s.connect(('localhost',9999))
threading.Thread(name='Rx', target=rxWorker).start()
threading.Thread(name='Tx', target=txWorker).start()
这适用于在另一个终端上运行的netcat侦听器:
nc -l localhost 9999
此时一切正常。线路从一侧发送到另一侧,并按预期显示。
现在输入已更改为立即输入,因此python端会在键入时发送字符(不等待换行符),如下所示:
导入套接字 导入线程 进口机 导入系统
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
def rxWorker():
while(True):
r = s.recv(1)
print(r.decode('ascii'), end='')
def txWorker():
while (True):
# i = input('')
i = getch.getche()
s.send(i.encode())
s.connect(('localhost',9999))
threading.Thread(name='Rx', target=rxWorker).start()
threading.Thread(name='Tx', target=txWorker).start()
请注意,唯一的变化是读取输入的方式:i = getch.getche()
与i = input('')
现在的行为有所不同。
python端的字符正确并立即显示在netcat端。
问题:netcat一侧的字符现在不会立即显示在python一侧。 实际上,直到将一个或几个字符从python发送到netcat之前,您实际上都不会显示。
这很奇怪,有点破坏我的控制流程/:
请告知
系统:Ubuntu 16.04,Python 3.5.2
答案 0 :(得分:2)
主要问题是您实际上尚未启用TCP_NODELAY
。
此行不执行您认为的操作:
s = socket.socket(socket.AF_INET, socket.TCP_NODELAY )
socket
的参数为:
socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
碰巧的是,至少在* nix系统上,TCP_NODELAY
是1
,而SOCK_STREAM
是一个值为1
的枚举,因此通过传递{{ 1}}作为您选择的TCP_NODELAY
类型,也就是TCP。当SOCK_STREAM
库的将来版本切换为对socket
值使用枚举时(就像已经对类型使用的那样),它将变成sockopt
而不是无声地做一些偶然的事情碰巧是某种工作。
如果要启用TypeError
之类的sockopt
值,则必须在套接字上调用setsockopt
。像这样:
TCP_NODELAY
请注意,您的代码中至少还有一个其他明显的错误,尽管它没有引起任何问题:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
rxt = threading.Thread(name='Rx', target=rxWorker).start()
返回Thread.start
。因此,您看到None
(和rxt
)到txt
。幸运的是,您实际上并没有对它们做任何事情,但是一旦您这样做,例如None
,您将得到rxt.join()
。