将 stdin 管道传输到 TCP 服务器时 Socat 挂起

Socat hangs when piping stdin to tcp server

我有一个嵌入式 linux 系统 运行 一个 tcp 服务器。 Telnet 可以很好地交互连接和使用 tcp 服务器。

我正在尝试使用 socat 建立相同的连接,方法是将 stdin 链接到 tcp 服务器,如下所示:

socat - tcp:localhost:8088

我得到了服务器的初始响应,我可以输入,但是我一按回车,终端就挂了(我可以用 Ctrl + C 退出这个,只要我不使用原始的socat 选项。)

如果我用 readline 做同样的事情,一切都会按预期进行:

socat readline tcp:localhost:8088

但是,使用readline,终端会回显我的输入,然后服务器的响应也会回显。这不仅仅是一个烦恼,因为像密码这样的东西(甚至不应该回显一次)现在是可见的。

理想情况下,我会使用 stdin 而不是 readline,这样我就可以在输入每个字符后立即发送它,并关闭 stdin echo。这样,当我键入一个字符时,tcp 服务器会收到它并立即回显,但前提是它应该如此。

但是由于我不明白的原因,socat 与 stdin 选项挂起。

我正在寻找关于为什么 stdin 锁定线程的解释,或者可能使用 readline 或类似方法的解决方法。

编辑:这是我使用标准输入时 socat 命令的 dddd 调试输出:

sh-5.0# socat -d -d -d -d -lu - tcp:localhost:8088

2022/02/04 01:34:58.805536 socat[1074] D getpid()

2022/02/04 01:34:58.807631 socat[1074] D getpid() -> 1074

2022/02/04 01:34:58.807667 socat[1074] D setenv("SOCAT_PID", "1074", 1)

2022/02/04 01:34:58.807687 socat[1074] D setenv() -> 0

2022/02/04 01:34:58.807704 socat[1074] D setenv("SOCAT_PPID", "1074", 1)

2022/02/04 01:34:58.807724 socat[1074] D setenv() -> 0

2022/02/04 01:34:58.807737 socat[1074] I socat by Gerhard Rieger and contributors - see www.dest-unreach.org

2022/02/04 01:34:58.807752 socat[1074] I This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)

2022/02/04 01:34:58.807767 socat[1074] I This product includes software written by Tim Hudson (tjh@cryptsoft.com)

2022/02/04 01:34:58.807781 socat[1074] D socat version 1.7.3.3 on May 25 2021 13:47:29

2022/02/04 01:34:58.807795 socat[1074] D setenv("SOCAT_VERSION", "1.7.3.3", 1)

2022/02/04 01:34:58.807811 socat[1074] D setenv() -> 0

2022/02/04 01:34:58.807827 socat[1074] D running on Linux version #1 SMP Mon Jan 31 20:48:32 UTC 2022, release 5.4.0, machine aarch64

2022/02/04 01:34:58.807845 socat[1074] D argv[0]: "socat"

2022/02/04 01:34:58.807857 socat[1074] D argv[1]: "-d"

2022/02/04 01:34:58.807870 socat[1074] D argv[2]: "-d"

2022/02/04 01:34:58.807883 socat[1074] D argv[3]: "-d"

2022/02/04 01:34:58.807895 socat[1074] D argv[4]: "-d"

2022/02/04 01:34:58.807907 socat[1074] D argv[5]: "-lu"

2022/02/04 01:34:58.807920 socat[1074] D argv[6]: "-"

2022/02/04 01:34:58.807932 socat[1074] D argv[7]: "tcp:localhost:8088"

2022/02/04 01:34:58.807945 socat[1074] D sigaction(1, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.807960 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.807973 socat[1074] D sigaction(2, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.807987 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808000 socat[1074] D sigaction(3, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.808014 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808026 socat[1074] D sigaction(4, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.808040 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808053 socat[1074] D sigaction(6, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.808067 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808079 socat[1074] D sigaction(7, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.808092 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808105 socat[1074] D sigaction(8, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.808119 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808132 socat[1074] D sigaction(11, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.808146 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808158 socat[1074] D sigaction(15, 0xffffc8d63a18, 0x0)

2022/02/04 01:34:58.808172 socat[1074] D sigaction() -> 0

2022/02/04 01:34:58.808185 socat[1074] D signal(13, 0x1)

2022/02/04 01:34:58.808200 socat[1074] D signal() -> 0x0

2022/02/04 01:34:58.808213 socat[1074] D atexit(0xaaaaba73c4a0)

2022/02/04 01:34:58.808226 socat[1074] D atexit() -> 0

2022/02/04 01:34:58.808267 socat[1074] D calloc(1, 848)

2022/02/04 01:34:58.808284 socat[1074] D calloc() -> 0xaaaadd2cc680

2022/02/04 01:34:58.808304 socat[1074] D malloc(1024)

2022/02/04 01:34:58.808318 socat[1074] D malloc() -> 0xaaaadd2cca00

2022/02/04 01:34:58.808333 socat[1074] D calloc(1, 848)

2022/02/04 01:34:58.808350 socat[1074] D calloc() -> 0xaaaadd2cce10

2022/02/04 01:34:58.808364 socat[1074] D calloc(1, 848)

2022/02/04 01:34:58.808377 socat[1074] D calloc() -> 0xaaaadd2cd170

2022/02/04 01:34:58.808391 socat[1074] D isatty(0)

2022/02/04 01:34:58.808411 socat[1074] D isatty() -> 1

2022/02/04 01:34:58.808424 socat[1074] D tcgetattr(0, 0xaaaadd2ccf6c)

2022/02/04 01:34:58.808461 socat[1074] D tcgetattr(, {00005400,00000005,00001cb2,0000083b, 4098,4098, 03,1c,7f,15,04,00,01,00,11,13,1a,00,12,0f,17,16,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00}) -> 0

2022/02/04 01:34:58.808480 socat[1074] D isatty(1)

2022/02/04 01:34:58.808494 socat[1074] D isatty() -> 1

2022/02/04 01:34:58.808507 socat[1074] D tcgetattr(1, 0xaaaadd2cd2cc)

2022/02/04 01:34:58.808542 socat[1074] D tcgetattr(, {00005400,00000005,00001cb2,0000083b, 4098,4098, 03,1c,7f,15,04,00,01,00,11,13,1a,00,12,0f,17,16,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00}) -> 0

2022/02/04 01:34:59.141868 socat[1074] D malloc(128)

2022/02/04 01:34:59.141888 socat[1074] D malloc() -> 0xaaaadd2cd4d0

2022/02/04 01:34:59.141903 socat[1074] D malloc(128)

2022/02/04 01:34:59.141916 socat[1074] D malloc() -> 0xaaaadd2cd560

2022/02/04 01:34:59.141931 socat[1074] N reading from and writing to stdio

2022/02/04 01:34:59.141946 socat[1074] D calloc(1, 848)

2022/02/04 01:34:59.141959 socat[1074] D calloc() -> 0xaaaadd2cd5f0

2022/02/04 01:34:59.141983 socat[1074] D malloc(1024)

2022/02/04 01:34:59.141997 socat[1074] D malloc() -> 0xaaaadd2cd9b0

2022/02/04 01:34:59.142015 socat[1074] D getaddrinfo("localhost", NULL, {1,0,1,6,0,0x0,0x0,0x0}, 0xffffc8d63538)

2022/02/04 01:34:59.142789 socat[1074] D getaddrinfo(,,,{{AF=10 [0000:0000:0000:0000:0000:0000:0000:0001]:0, }) -> 0

2022/02/04 01:34:59.142815 socat[1074] D malloc(128)

2022/02/04 01:34:59.142830 socat[1074] D malloc() -> 0xaaaadd2ce610

2022/02/04 01:34:59.142847 socat[1074] N opening connection to AF=2 127.0.0.1:8088

2022/02/04 01:34:59.142861 socat[1074] I starting connect loop

2022/02/04 01:34:59.142876 socat[1074] D socket(2, 1, 6)

2022/02/04 01:34:59.142900 socat[1074] I socket(2, 1, 6) -> 5

2022/02/04 01:34:59.142919 socat[1074] D fcntl(5, 2, 1)

2022/02/04 01:34:59.142935 socat[1074] D fcntl() -> 0

2022/02/04 01:34:59.142954 socat[1074] D connect(5, {2,AF=2 127.0.0.1:8088}, 16)

2022/02/04 01:34:59.145199 socat[1074] D connect() -> 0

2022/02/04 01:34:59.145246 socat[1074] D getsockname(5, 0xffffc8d635b8, 0xffffc8d6359c{112})

2022/02/04 01:34:59.145269 socat[1074] D getsockname(, {AF=2 127.0.0.1:46294}, {16}) -> 0

2022/02/04 01:34:59.145286 socat[1074] N successfully connected from local address AF=2 127.0.0.1:46294

2022/02/04 01:34:59.145306 socat[1074] I resolved and opened all sock addresses

2022/02/04 01:34:59.145321 socat[1074] D malloc(16385)

2022/02/04 01:34:59.145344 socat[1074] D malloc() -> 0xaaaadd2cf400

2022/02/04 01:34:59.145360 socat[1074] N starting data transfer loop with FDs [0,1] and [5,5]

2022/02/04 01:34:59.145375 socat[1074] D data loop: sock1->eof=0, sock2->eof=0, closing=0, wasaction=1, total_to={0.000000}

2022/02/04 01:34:59.145395 socat[1074] D select(6, &0x21, &0x22, &0x0, NULL/0.000000)

2022/02/04 01:34:59.145426 socat[1074] D select -> (, 0x0, 0x20, 0x0, NULL/0.000000), 1

2022/02/04 01:34:59.145443 socat[1074] D data loop: sock1->eof=0, sock2->eof=0, closing=0, wasaction=1, total_to={0.000000}

2022/02/04 01:34:59.145461 socat[1074] D select(6, &0x21, &0x2, &0x0, NULL/0.000000)

2022/02/04 01:34:59.157132 socat[1074] D select -> (, 0x20, 0x0, 0x0, NULL/0.000000), 1

2022/02/04 01:34:59.157178 socat[1074] D data loop: sock1->eof=0, sock2->eof=0, closing=0, wasaction=1, total_to={0.000000}

2022/02/04 01:34:59.157198 socat[1074] D select(2, &0x1, &0x2, &0x0, NULL/0.000000)

2022/02/04 01:34:59.401692 socat[1074] D select -> (, 0x0, 0x2, 0x0, NULL/0.000000), 1

2022/02/04 01:34:59.401732 socat[1074] D read(5, 0xaaaadd2cf400, 8192)

2022/02/04 01:34:59.401765 socat[1074] D read -> 48

2022/02/04 01:34:59.401782 socat[1074] D write(1, 0xaaaadd2cf400, 48)

ÿûÿû

Connect to IP address 169.254.12.16

2022/02/04 01:34:59.401809 socat[1074] D write -> 48

2022/02/04 01:34:59.401823 socat[1074] 我从5传输了48个字节 到 1

2022/02/04 01:34:59.401838 socat[1074] D数据循环:sock1->eof=0, sock2->eof=0, closing=0, wasaction=1, total_to={0.000000}

2022/02/04 01:34:59.401856 socat[1074] D select(6, &0x21, &0x2, &0x0, NULL/0.000000)

2022/02/04 01:34:59.462969 socat[1074] D select -> (, 0x0, 0x2, 0x0, NULL/0.000000), 1

2022/02/04 01:34:59.463017 socat[1074] D数据循环:sock1->eof=0, sock2->eof=0, closing=0, wasaction=1, total_to={0.000000}

2022/02/04 01:34:59.463036 socat[1074] D select(6, &0x21, &0x0, &0x0, NULL/0.000000)

此时,我仍然可以打字,但无论我做什么,我都没有得到任何回应。

可能不是Socat挂了,而是服务器挂了。使用选项 -v -x 查看 Socat 在两种情况下传输的数据并进行比较;可能涉及不同的行终止符。

事实证明这是多种因素的结合。

  1. 我使用的 socat 版本 (1.7.3.3) 在使用某些选项时存在错误。有关详细信息,请参阅 https://bugs.launchpad.net/ubuntu/+source/socat/+bug/1883957
  2. 我终端中的 tty 选项有点不典型。通过使用“stty sane”,然后添加 -brkint,我得到了与 stdin 一起工作的整个过程。

我的最终解决方案使用 socat 版本 1.7.4.3,如下所示:

stty sane

stty -brkint -icanon && socat -,echo=0 tcp:localhost:8088