在持有 TCP 连接的文件描述符上使用“echo”命令破坏管道

问题描述 投票:0回答:1

看完文章https://www.xmodulo.com/tcp-udp-socket-bash-shell.html,我试着写了一个简单的脚本:

#!/bin/bash

exec 3<>/dev/tcp/time.nist.gov/13

for i in {1..3}; do
    echo -e "GET / HTTP/1.1\r\nhost: service\r\nConnection: close\r\n\r\n" >&3
    cat <&3
    echo "get sent"
    sleep 10
done
exec 3<&-
echo "done"

它成功地返回了我的时间,但只有“错误的文件描述符”。

但是如果我移动文件描述符 3 的打开和打开,它运行良好

#!/bin/bash

for i in {1..3}; do
    exec 3<>/dev/tcp/time.nist.gov/13
    echo -e "GET / HTTP/1.1\r\nhost: service\r\nConnection: close\r\n\r\n" >&3
    cat <&3
    echo "get sent"
    exec 3<&-
    sleep 10
done

echo "done"

为什么会这样?

(我更愿意保持 TCP 套接字打开而不关闭并重新打开它。)

bash sockets file-descriptor io-redirection
1个回答
1
投票

13端口是daytime协议,不是HTTP。因此,首先向服务器发送 HTTP 请求是错误的。相反,必须遵循白天协议的规范 - 请参阅维基百科:白天协议以获得概述。

基本上,该协议通过连接到服务器并读取直到连接关闭来工作——客户端根本不发送任何应用程序数据。由于必须阅读直到连接关闭并且没有“请求”的概念,因此也无法保持连接打开以获取更多“请求”。相反,必须为每个新查询创建一个新连接。

for i in {1..3}; do
    exec 3<>/dev/tcp/time.nist.gov/13
    cat <&3
    exec 3<&-
    sleep 10
done
echo "done"

但即使对方是 HTTP 服务器,尝试过的方法也行不通。其一:HTTP 请求明确要求

Connection: close
,因此排除了同一连接上的多个请求。并且,
cat <&3
一直读取到服务器关闭连接而不是 HTTP 响应结束,这使得在同一连接上获得多个响应,因此也无法进行多个请求。

© www.soinside.com 2019 - 2024. All rights reserved.