我试图在Python中复制这个socat
命令的行为:
socat PTY,link=/tmp/mypty tcp-listen:1234
到服务器端口1234的TCP连接将连接到/tmp/mypty(指向/dev/pts/N的链接),运行screen /tmp/mypty
将允许用户与该连接另一端的任何内容进行交互。换句话说,如果这用于连接到该侦听端口:
然后运行screen /tmp/mypty
将用户连接到在TCP连接的另一端运行的bash
的实例。在
获取TCP套接字很简单。我可以找个私人助理来用操作系统openpty(),这会产生一对文件描述符,它们只是整数。在
我做不到的是用一种无缝地来回传递数据的方式钩住套接字和那些文件描述符。如果这两个套接字都是,那么这将是微不足道的;使用带有select()的循环将新的read数据传递给另一个套接字的write。在
我所做的:
OSError: [Errno 88] Socket operation on non-socket
。此代码的示例,其中clisock是有效的套接字:def sockToPty(clisock,addr): (master, slave) = os.openpty() print('PTY: Opening {}'.format(os.ttyname(slave))) ptymsock = socket.fromfd(master, socket.AF_UNIX, socket.SOCK_STREAM) ptyssock = socket.fromfd(slave, socket.AF_UNIX, socket.SOCK_STREAM) print('CLISOCK: {}'.format(clisock)) print('PTYMSOCK: {}'.format(ptymsock)) print('PTYSSOCK: {}'.format(ptyssock)) peer[clisock] = ptymsock peer[ptyssock] = clisock while True: iready, oready, eready = select.select([clisock, ptyssock], [], []) for sock in iready: data = sock.recv(4096) if not len(data): return peer[sock].send(data)
从而导致此错误:
PTY: Opening /dev/pts/2 CLISOCK: PTYMSOCK: PTYSSOCK: Exception in thread Thread-1: Traceback (most recent call last): File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner self.run() File "/usr/lib/python3.6/threading.py", line 864, in run self._target(*self._args, **self._kwargs) File "./tcpmux.py", line 62, in sockToPty peer[sock].send(data) OSError: [Errno 88] Socket operation on non-socket
如果我使用AF_INET而不是AF_UNIX,也没有什么不同。在
screen
打开PTY时,没有明显的数据流。在几乎所有Python PTY示例都集中在pty.产卵(),这使得很难找到PTY的这种(公认的晦涩)用法的示例代码。在
旁注:我正在使用操作系统openpty而不是私人有限公司只是因为似乎没有意义。pty模块似乎被宣传为具有更多的可移植性,但并不是要有更多的可移植性,而且我正在研究Linux,所以可移植性不是一个问题。既然我得到了正确的文件描述符操作系统名称(),我没有理由质疑openpty()不能正常工作。在
可以使用选择投票()而不是选择。选择(),因为选择投票()将同时使用文件描述符和套接字。在
这段代码比简单套接字所需的代码复杂得多—对于TCP套接字,您可以简单地将该套接字的fileno()用作文件描述符,然后以相同的方式对待两边(操作系统读取(), 操作系统写入()). 但是,如果要在SSLSocket中使用它,则需要上面更复杂的版本,因为如果从SSLSocket获取fileno(),那么它期望您处理TLS层和数据。在
相关问题 更多 >
编程相关推荐