You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Radmin VPN环境下TCP Socket控制台通讯程序连接失败及异常断连问题求助

Radmin VPN环境下TCP Socket控制台通讯程序连接失败及异常断连问题求助

兄弟,我看了你的代码和遇到的问题,给你梳理下具体的排查点和修复方案:


一、初始跨Radmin VPN连接失败的排查方向

你说自己连本地能通,但和朋友用Radmin连不上,先从这几个点排查:

  1. 先确认Radmin VPN网络连通性
    让你和朋友互相ping对方的Radmin VPN分配的IP(可以在Radmin客户端里看到),如果ping不通,那是Radmin本身的网络问题,先解决这个——比如检查Radmin是否在同一个网络组,两边的Radmin客户端是否正常运行。

  2. 防火墙权限要配置对
    光给程序开权限可能不够,得确保:

    • Host端:Windows防火墙(或第三方防火墙)允许TCP入站连接到你程序用的端口(如果是随机端口,就临时关闭防火墙测试,排除这个因素)
    • Client端:允许TCP出站连接到Host的Radmin IP和对应端口
      可以先临时关闭两边的防火墙测试,能连上的话再回来配置防火墙规则。
  3. 代码里Host端的端口和IP提示要准确
    你现在的Host端代码绑定的是IPAddress.Any, 0,系统会随机分配端口,而且LocalEndPoint显示的是0.0.0.0:xxxx,但朋友要连的是你Radmin VPN的IP(比如192.168.5.3)加上这个随机端口,不是0.0.0.0
    建议改成固定端口,比如把绑定代码改成:

    IPEndPoint iPEndPoint = new(IPAddress.Any, 12345); // 用固定端口12345
    serverSocket.Bind(iPEndPoint);
    

    然后Host端输出提示的时候,显示自己的Radmin IP和固定端口,比如:

    // 可以手动填写自己的RadminIP,或者通过代码枚举网卡自动获取
    Console.WriteLine($"Waiting for connection on your Radmin IP: 你的RadminIP:12345");
    

    这样朋友连接的时候直接填你的Radmin IP和12345就行,不用记随机端口。


二、连接后发几条消息就断连的修复方案

看你的代码,断连的核心问题是没有处理Socket连接断开的信号,也没有捕获异常,导致循环在连接断开后继续执行抛出异常。给你改了关键部分的代码:

1. 修复接收消息循环(处理断开信号和异常)

原来的接收循环没处理Receive返回0的情况(远程断开连接时Receive会返回0),也没捕获Socket异常,改成这样:

private static async Task ReceiveMessagesLoopAsync(Socket friend)
{
    byte[] buffer = new byte[512];
    while (true)
    {
        try
        {
            int bytesRead = friend.Receive(buffer);
            // 远程关闭连接时,Receive返回0
            if (bytesRead == 0)
            {
                Console.WriteLine("\n对方已主动断开连接");
                break;
            }
            string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            Console.WriteLine($"[{friend.RemoteEndPoint}] {message}");
        }
        catch (SocketException ex)
        {
            Console.WriteLine($"\n连接异常断开: {ex.Message}");
            break;
        }
    }
    // 断开后退出程序
    Environment.Exit(0);
}

2. 修复发送消息循环(捕获发送异常)

发送的时候如果连接断开,Send会抛出异常,也要处理:

private static void SendMessagesInLoop(Socket friend)
{
    while (true)
    {
        string messageToSend = "";
        Console.Write("[You]: "); // 加个输入提示,更直观
        ConsoleKeyInfo keyInfo = new();
        
        while (keyInfo.Key != ConsoleKey.Enter)
        {
            keyInfo = Console.ReadKey(true); // 用true避免重复输出字符
            if (keyInfo.Key == ConsoleKey.Enter)
                break;
            else if (keyInfo.Key == ConsoleKey.Backspace)
            {
                if (messageToSend.Length > 0)
                {
                    Console.Write(" \b");
                    messageToSend = messageToSend.Remove(messageToSend.Length - 1);
                }
                continue;
            }
            messageToSend += keyInfo.KeyChar;
            Console.Write(keyInfo.KeyChar);
        }
        Console.WriteLine(); // 回车后换行
        
        try
        {
            byte[] buffer = Encoding.UTF8.GetBytes(messageToSend);
            friend.Send(buffer);
        }
        catch (SocketException ex)
        {
            Console.WriteLine($"发送失败,连接已断开: {ex.Message}");
            break;
        }
    }
    Environment.Exit(0);
}

3. 异步任务创建优化

原来用Task receiveMessageLoop = new(...)然后Start()的方式不太规范,改成用Task.Run

// 替换原来的任务创建代码
Task receiveMessageLoop = Task.Run(() => ReceiveMessagesLoopAsync(friend));

三、其他小优化建议

  • 接收消息的方法名改成ReceiveMessagesLoopAsync,并且返回Task而不是void,符合C#异步方法的命名规范
  • 可以加个全局的CancellationToken来优雅地停止循环,而不是直接Environment.Exit(0),不过控制台程序用Exit也没问题
  • 原来的ClearCurrentConsoleLine方法可能在某些窗口大小下有问题,改成上面代码里的手动输入回显更稳定

按照这些改完,先测试Radmin的ping连通性,再试程序,应该能解决你的问题啦!

火山引擎 最新活动