【发布时间】: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。