在 bash 中,我可以异步打开套接字并稍后使用它们吗?

在 bash 中,我可以异步打开套接字并稍后使用它们吗?

我没想到 Bash 支持这么多高级功能!我开始开发一个简单的网络程序来尝试使用我发现的一些东西。我的特定程序是一个完全用 Bash 编写的基本 Redis 客户端。目前,我可以执行以下操作:

redis_command -c "ping" redis{001..100}:{6379..6400}

它将向所有实例(大约 2100 个)发送“ping”命令并​​返回结果。我目前正在串行发送“ping”命令,但我认为可以通过并行执行所有初始套接字创建来加速我的程序。我在有/没有优化的情况下测试了我的程序,并意识到我的优化实际上减慢了速度。优化效果如下:

declare -A SOCKETS
function get_socket {
  # args: <hostname> <port>
  # returns: the socket number, or failure return code

  # verify args
  if [[ -z "${1}" ]]; then
    return 1
  fi
  if [[ -z "${2}" ]]; then
    return 1
  fi

  local HOSTPORT="${1}:${2}"
  if [[ -z ${SOCKETS[${HOSTPORT}]} ]]; then
    exec {fd}<>/dev/tcp/${1}/${2}
    SOCKETS[${HOSTPORT}]=${fd}
    RES=${fd}
  else
    RES="${SOCKETS[${HOSTPORT}]}"
  fi
}

if [[ ${PRECONNECT} -eq 1 ]]; then
  echo -n "Pre-connecting to ${#HOSTS[@]} instances... " >&2
  for HOST in ${HOSTS[@]}; do
    get_socket "${HOST%%:*}" "${HOST##*:}" &
    PIDS+=($!)
  done

  # make sure all of our async connections finished before starting
  # TODO, check for errors
  for PID in ${PIDS[@]}; do
    wait ${PID}
  done
  echo "done" >&2
fi

通常, get_socket() 函数本身就可以很好地工作。如果我需要向特定服务器发送命令,我会提前调用 get_socket(),并将 FD 传递给另一个实际发送命令并解析响应的函数。在预连接场景中,我通过 & 在后台调用 get_socket。由于 get_socket()& 在单独的进程中运行,因此创建的 FD 在调用进程中不可用/不可访问,因此我的优化毫无用处。

有没有什么方法可以在 bash 中发送套接字,或者有其他方法可以在不使用单独进程的情况下并行化我的连接?

答案1

不能/dev/tcp/x/y直接使用,但您可以使用管道与后台启动的进程进行通信,以连接 TCP 套接字并传输数据。

就像是

coproc hostA {
  exec {fd}<> /dev/tcp/127.0.0.1/80
  cat <&$fd & cat >&$fd
}

# same for hostB...

echo -e 'HEAD / HTTP/1.0\r\n\r' >&${hostA[1]}
cat <&${hostA[0]}

无论如何,当您最终运行两个cat命令时,您最好不使用/dev/tcp(并不总是启用)并使用例如 socat:

coproc hostA { socat - tcp:localhost:80; }

或者,您可以使用命名管道来删除对 bash 的依赖:

mkfifo hostA.in hostA.out
socat - tcp:localhost:80 < hostA.in > hostA.out &

相关内容