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

Linux(SLES 12) socat TCP监听器对接.NET(C#)客户端技术问询

我来帮你梳理下C# .NET原生套接字对接socat监听器的实现思路和代码示例,结合你的场景(socat调用hello.sh处理传入字符串并返回结果),以下是具体步骤和注意事项:

1. 基础实现示例

.NET里可以用封装后的TcpClient(简洁易用)或者底层的Socket(原生套接字)来实现,先从TcpClient的方案开始:

TcpClient 实现(推荐,封装度高)

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;

class SocatTcpClient
{
    static void Main(string[] args)
    {
        // 替换为你的socat监听器IP和端口
        string serverIp = "192.168.1.100";
        int port = 12345;

        try
        {
            // 建立TCP连接,using自动释放资源
            using TcpClient client = new TcpClient(serverIp, port);
            Console.WriteLine("已成功连接到socat监听器");

            // 获取网络流用于读写数据
            using NetworkStream stream = client.GetStream();

            // 发送需要处理的字符串
            string inputString = "test_input";
            byte[] sendBuffer = Encoding.UTF8.GetBytes(inputString);
            stream.Write(sendBuffer, 0, sendBuffer.Length);
            Console.WriteLine($"已发送数据: {inputString}");

            // 接收脚本返回的结果(循环读取确保拿到完整数据)
            using MemoryStream responseStream = new MemoryStream();
            byte[] receiveBuffer = new byte[1024];
            int bytesRead;

            // 循环读取直到流中无数据
            while (stream.DataAvailable || client.Available > 0)
            {
                bytesRead = stream.Read(receiveBuffer, 0, receiveBuffer.Length);
                if (bytesRead == 0) break;
                responseStream.Write(receiveBuffer, 0, bytesRead);
            }

            string response = Encoding.UTF8.GetString(responseStream.ToArray());
            Console.WriteLine("\n收到脚本返回结果:");
            Console.WriteLine(response);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"通信出错: {ex.Message}");
        }
    }
}

原生Socket 实现(底层控制)

如果需要更底层的套接字控制,可以直接使用Socket类:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

class NativeSocketClient
{
    static void Main(string[] args)
    {
        string serverIp = "192.168.1.100";
        int port = 12345;
        IPAddress ipAddr = IPAddress.Parse(serverIp);
        IPEndPoint remoteEndpoint = new IPEndPoint(ipAddr, port);

        // 创建原生TCP套接字
        using Socket clientSocket = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

        try
        {
            // 发起连接
            clientSocket.Connect(remoteEndpoint);
            Console.WriteLine($"已连接到 {remoteEndpoint}");

            // 发送数据
            string inputString = "test_input";
            byte[] sendBuffer = Encoding.UTF8.GetBytes(inputString);
            int bytesSent = clientSocket.Send(sendBuffer);
            Console.WriteLine($"已发送 {bytesSent} 字节: {inputString}");

            // 接收返回结果
            byte[] receiveBuffer = new byte[1024];
            StringBuilder responseBuilder = new StringBuilder();
            int bytesRead;

            while (clientSocket.Available > 0)
            {
                bytesRead = clientSocket.Receive(receiveBuffer);
                responseBuilder.Append(Encoding.UTF8.GetString(receiveBuffer, 0, bytesRead));
            }

            Console.WriteLine("\n收到脚本返回结果:");
            Console.WriteLine(responseBuilder.ToString());

            // 关闭套接字
            clientSocket.Shutdown(SocketShutdown.Both);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"出错: {ex.Message}");
        }
    }
}
2. 针对你的场景的关键注意事项
  • 数据边界处理:socat转发脚本输出时,若脚本执行完成后未主动退出,socat可能会保持连接,导致单次Read无法获取完整数据。上面的示例用循环读取+判断DataAvailable/Available来解决,也可以和脚本约定结束标记(比如输出末尾加END_OF_OUTPUT),客户端读到标记后停止读取。
  • 编码一致性:确保C#客户端的编码(示例用UTF8)与hello.sh的输出编码一致。SLES12默认编码通常是UTF8,若脚本用其他编码,需同步修改C#中的Encoding(比如Encoding.GetEncoding("ISO-8859-1"))。
  • socat启动命令验证:确认你的socat命令包含fork参数,确保每个客户端连接都启动独立的hello.sh进程,避免阻塞:
    socat TCP-LISTEN:12345,fork EXEC:./hello.sh
    
3. 调试与排错技巧
  • 先通过ncat/telnet验证连接和数据传输正常,排除网络或socat配置问题。
  • 若出现乱码,检查双方编码是否一致,可在脚本中强制指定输出编码(比如echo "result" | iconv -f UTF-8 -t UTF-8)。
  • 用Wireshark抓包查看TCP报文,确认数据是否正常发送/接收,定位丢包或截断问题。
  • 在C#中打印client.Available的值,查看是否有未读取的字节,判断是否需要调整读取逻辑。

内容的提问来源于stack exchange,提问作者Abhishek Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:33:00