【问题标题】:socat blocking on stdinsocat 在标准输入上阻塞
【发布时间】:2013-01-25 09:39:35
【问题描述】:

我在 AIX 主机 myscript.sh 上有如下 bash 脚本:

MODE="$1"
if [ "$MODE" == "start" ]; then
    socat -T100 -lf $LOGF -d -d -d -x TCP4-LISTEN:$LISTENINGPORT,bind=$LISTENINGADDR,reuseaddr,fork EXEC:"$0 proxy" &
    PID=$!
    echo $PID > $PIDFILE
    echo "$0 $MODE started (pid=$PID)"

elif [ "$MODE" == "proxy" ]; then
    cat - > $TMPFILE
    # process $TMPFILE before the SSL connection.
    cat $TMPFILE | socat -T 100 -lf $LOGF -d - OPENSSL:$HOST
    rm -f $TMPFILE

我跑的时候一切都很好:

$ cat somefile | myscript.sh proxy | xxd

当我使用测试脚本连接到 socat 侦听器时出现问题:

my $file = $ARGV[0];
my $fsize = -s $file;
my $socket = IO::Socket::INET->new("127.0.0.1:$port")
    or die "Couldn't connect to remote host: $!";
$socket->autoflush(1);
binmode($socket);
open (FILE,$file);
binmode(FILE);
my $buffer ;
while(sysread(FILE, $buffer, $blocksize)) {
    print $socket $buffer ;
}
print "sent\n" ;
close (FILE) ;

my $answer = <$socket>;
if (defined($answer)) {
    print $answer; # never reached
print "...\n" ;
} else {
    die "connection reset by peer\n";
}

在myscript.sh中,它阻塞就行了:

cat - > $TMPFILE

在测试脚本中,阻塞就行了:

my $answer = <$socket>;

此时,socat监听器已经接收到数据(用tcpdump检查)。

但是,当我在 socat 超时之前 Ctrl+c 测试脚本时,数据会通过管道(即最终联系 SSL 服务器)。

我做错了什么?

更新: 感谢您提供有关 cat 和 EOF 的提示。目前,我已经解决了这样的问题:

timeout 0.2 cat -u - > $TMPFILE 2>>/dev/null
# process $TMPFILE before the SSL connection.
cat $TMPFILE | socat -T 100 -lf $LOGF -d - OPENSSL:$HOST

很丑,浪费0.2秒,希望能找到更好的解决方案。 但它现在完成了这项工作。 2>>/dev/null 部分是因为 AIX 抱怨计数器无效(与 timeout 命令有关)。

【问题讨论】:

  • 这个脚本是用 Perl 写的吗? my $answer = &lt;$socket&gt;; 的左/右尖括号是什么?此外,在 shell 脚本中,当您从标准输入 (cat -) 接收数据时,它何时终止?
  • 是的,测试脚本是用perl写的。括号的意思是“阅读任何可读的内容”,我很乐意阅读一个字节。是的,当测试脚本被杀死时,我从标准输入中得到了整个东西。
  • 对不起,我肯定没说清楚;我的第二个问题是,标准输入流何时终止?如果你没有收到EOF,是的,cat 将被卡在它的执行中——直到你按下 Ctrl+c,正如你所说的。
  • 我的帖子更新了,谢谢提示
  • 所以现在你真的在接收数据一段时间后杀死cat - 。数据从何而来,数据发送者本身不能向cat - 发送终止消息吗?我的意思是,它进入了标准输入,但是是你在向文件中输入内容,还是来自打开的连接?

标签: perl bash ssl aix socat


【解决方案1】:

我的第一个想法是,您尝试使用 cat -&lt;STDIN&gt; 接收的数据中没有换行符。一旦有换行符或文件描述符的缓冲区已满(Linux 中默认为 4KB),这两个命令的默认行为都会返回数据。

【讨论】:

  • 确实没有换行。这是需要通过 SSL 传输的二进制协议聊天
  • 您发送多少数据?在 perl 中尝试read,长度为 1,在这种情况下它应该会很快返回。
  • 数据量在 0.5k 到 3k 之间变化。你将如何从 bash 调用“perl read”?
猜你喜欢
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 2021-12-07
  • 2015-12-31
相关资源
最近更新 更多