You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何这段TCP Echo Haskell代码无法获取返回结果?

问题分析与修复

你的Haskell代码无法收到tcpbin.com Echo服务响应的原因有几个关键问题,下面逐个拆解并给出修复方案:

核心问题点

  • 发送长度错误:你用sendBuf socket msg 100发送了100字节,但"hellooo"编码成UTF-8只有7个字节,这会导致ptr后面的93个随机内存数据被发送出去,服务器无法识别这是有效输入,因此不会返回回声。
  • 缺少触发响应的换行符:nc连接时你输入的内容带有换行(Hello server!+回车),而代码中发送的"hellooo"没有换行——tcpbin的Echo服务需要收到换行符才会触发响应逻辑。
  • 不必要的指针操作:已经导入了Network.Socket.ByteString的sendAll,完全可以直接发送ByteString,手动处理指针不仅冗余,还容易出错且造成内存泄漏。
  • 错误的addrFlags设置:AI_PASSIVE是给服务器端绑定监听端口用的,客户端连接远程服务器不需要这个标志,虽然不是直接导致问题的原因,但不符合规范。

修复后的代码

{-# LANGUAGE OverloadedStrings #-}

module Main where

import qualified Data.ByteString as BS
import Data.Text.Encoding
import Network.Socket
import Network.Socket.ByteString (recv, sendAll)

main = withSocketsDo $ do
  let hints =
        defaultHints
          { addrFlags = [],  -- 移除AI_PASSIVE,客户端不需要
            addrSocketType = Stream
          }
  let port = Just "4242"
  let address = Just "tcpbin.com"
  print "running..."
  addr <- getAddrInfo (Just hints) address port
  socket <- openSocket $ head addr
  connect socket (addrAddress (head addr))
  print "connected"
  -- 直接用encodeUtf8得到ByteString,添加换行符触发服务器响应
  let msg = encodeUtf8 "hellooo\n"
  sendAll socket msg
  print "sent bytes"
  -- 增大接收缓冲区,确保能收到完整响应
  bytes <- recv socket 1024
  print bytes

修复说明

  1. 移除AI_PASSIVE标志:客户端连接远程服务时不需要这个用于监听的标志,规范地址解析逻辑。
  2. 替换指针操作:用encodeUtf8直接将Text转为ByteString,通过sendAll发送,避免内存泄漏和长度错误,代码更简洁安全。
  3. 添加换行符:和nc的操作保持一致,触发服务器的Echo响应逻辑。
  4. 增大接收缓冲区:原代码只接收3字节,可能无法容纳完整响应,调整为1024字节更合理。

内容的提问来源于stack exchange,提问作者Mafaldo Reliedo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:55:24