【问题标题】:Connecting sockets over internet network fails通过 Internet 网络连接套接字失败
【发布时间】:2012-07-04 23:37:58
【问题描述】:

目录

  • 前言
  • 服务器端代码
  • 客户端代码
  • 本地计算机示例(成功
  • 互联网网络示例(不成功
  • 我的可能性考虑

前言

我从 MSDN 的类库示例中获取这些代码。所以它必须正常工作。是的,我部分正确。在我的电脑上运行时,它成功了。但是通过互联网,它失败了。我每次都使用 ConnectionRefused SocketErrorCode
下面我给出源码,一开始你一定知道我修改过的测试。

对于服务器代码:

  • 我使用 IPAddress.IPv6Any 而不是 IPAddress.Any
  • 我也试过没有 server.AllowNatTraversal(true)

但是失败了

服务器端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace ServerTest
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpListener server = null;
            try
            {
                int port = 13000;
                server = new TcpListener(IPAddress.Any, port);
                server.AllowNatTraversal(true);
                server.Start();
                byte[] bytes = new byte[256];
                string data = null;
                while (true)
                {
                    Console.WriteLine("Waiting for a connection...");
                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Connected: {0}", client.Client.LocalEndPoint.ToString());
                    data = null;
                    NetworkStream stream = client.GetStream();
                    int i;
                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        data = Encoding.ASCII.GetString(bytes, 0, i);
                        Console.WriteLine("Received: {0}", data);
                        data = data.ToUpper();
                        byte[] msg = Encoding.ASCII.GetBytes(data);
                        stream.Write(msg, 0, msg.Length);
                        Console.WriteLine("Sent: {0}", data);
                    }
                    client.Close();
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("Socket exception message: {0}", e.Message);
                Console.WriteLine("Socket Error Code: {0}", e.SocketErrorCode.ToString());
            }
            finally
            {
                server.Stop();
            }
            Console.WriteLine("\nHit enter to continue...");
            Console.ReadKey();            
        }
    }
}

客户端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace ClientTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Started...");
            Console.WriteLine("İP Address:");
            string hostName = Console.ReadLine();
            if(hostName.Length == 0)
            {
                hostName = Dns.GetHostName();
            }
            Connect(hostName, "hello");
        }

        static void Connect(string server, string message)
        {
            try
            {
                int port = 13000;
                TcpClient client = new TcpClient(server, port);
                byte[] data = Encoding.ASCII.GetBytes(message);
                NetworkStream stream = client.GetStream();
                stream.Write(data, 0, data.Length);
                Console.WriteLine("Sent: {0}", message);
                data = new byte[256];
                string responseData = string.Empty;
                int bytes = stream.Read(data, 0, data.Length);
                responseData = Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);
                stream.Close();
                client.Close();
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException: {0}", e.Message);
            }
            catch (SocketException e)
            {
                Console.WriteLine("Socket Error Code: {0}", e.SocketErrorCode.ToString());
            }
            Console.WriteLine("Hit enter to continue...");
            Console.ReadKey();
        }
    }
}

本地计算机示例(成功

我只在我的电脑上试过。首先我打开 ServerTest 程序,然后我运行 ClientText 程序。

客户端输出

开始...
İP 地址:

发送你好
收到你好
回车继续

服务器端输出

等待连接...
已连接:192.168.1.3:13000
收到:你好
发送:你好
等待连接

İinternet 网络示例(不成功

我和我的朋友尝试过,他的 IP 地址是“88.226.0.218”。他从whatismyipaddress.com 得知了他的 IP 地址,我运行了 ClientTest 程序,他运行了 ServerTest 程序。输出如下:

客户端输出

开始...
İP 地址:
88.226.0.218
SocketErrorCode: ConnectionRefused
回车继续

服务器端输出

正在等待连接...

什么都没有。 ServerTest 程序只等待。

我的可能性考虑

  • 当我使用 İPAddress.İPv6Any 时,它只能使用 İPv6
  • 我的调制解调器防火墙可以阻止 NatTraversal。如果是这样,我如何以编程方式启用调制解调器的 NatTraversal?
  • TcpListener 类的AllowNatTraversal 方法,.Net4 自带,不能正常工作。 (我不相信,但为了可能)

任何帮助将不胜感激。这对我来说非常重要。由于这次失败没有成功,我已经将我的项目推迟了将近一个月。

【问题讨论】:

  • 您肯定需要配置防火墙,以将到达您选择的公共端端口的流量传递到工作站上的相应端口。您的朋友可能会看到“连接被拒绝”消息,因为……您的防火墙正在拒绝传递到达该端口号的数据包。您如何执行此操作将根据您拥有的特定防火墙而有所不同。
  • 如果我们必须手动配置调制解调器 Nat,我更喜欢使用已经在使用的转发端口。是否已经转发了可用端口?
  • 当您说您更喜欢使用已在使用的转发端口时,我不确定我是否理解您的意思。在您的计算机上,您将无法将您的程序绑定到已被其他服务使用的端口号;在防火墙上,您将无法将公共接口上的一个端口转换为内部多个端口。虽然您的防火墙应该能够将外部的任意端口号 1:1 转换为内部的任意端口号,但它不会变成 1:* 或 *:1。

标签: .net sockets


【解决方案1】:

要尝试的一件事是在同一网络上的两台计算机之间进行测试。如果这可行,您可以将注意力从您的计算机转移开。

正如 Christopher 所说,无论如何,罪魁祸首很可能是防火墙。实际上,我会先检查您朋友的防火墙,因为某些(大多数?)防火墙不会阻碍传出连接。

此外,如果您的朋友在路由器后面,您需要让他在端口 13000 上将端口 13000 转发到他计算机的本地地址(很可能是 192.168.1.x)。

有关防火墙和端口转发的更多信息(和指南!)可以在这里找到:http://portforward.com/help/start_here.htm

【讨论】:

    猜你喜欢
    • 2012-08-25
    • 2011-01-16
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    相关资源
    最近更新 更多