我正在尝试使用TcpClient类连接到远程计算机,但它仍然失败:
“System.Net.Sockets.SocketException”类型的未处理异常 发生在System.dll
中其他信息:连接尝试失败,因为 连接方在一段时间后没有正确回应,或者 建立的连接失败,因为连接的主机失败了 响应
当客户端和服务器在本地工作时测试代码,但是当我尝试连接到远程计算机时,它不再有效。
这是服务器代码:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WebSocketServer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting a new WebSockets server.");
WebSocketServer server = new WebSocketServer();
Console.WriteLine("The WebSocket server has started.");
bool userRequestedShutdown = false;
while (!userRequestedShutdown)
{
Console.ReadLine();
DialogResult result = MessageBox.Show("Do you want to shut the server down?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (result == DialogResult.Yes)
{
userRequestedShutdown = true;
}
}
server.Stop();
}
class WebSocketServer
{
TcpListener server;
Thread connectionListener;
ConcurrentDictionary<TcpClient, Thread> clients = new ConcurrentDictionary<TcpClient, Thread>();
public WebSocketServer()
{
server = new TcpListener(IPAddress.Parse("127.0.0.1"), (int)Properties.Settings.Default["Port"]);
try
{
server.Start();
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to start the server: {0}", exception.ToString());
}
connectionListener = new Thread(() =>
{
while (true)
{
Console.WriteLine("Waiting for a new client.");
try
{
TcpClient client = server.AcceptTcpClient();
Thread clientListener = new Thread(() =>
{
try
{
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[1024];
Console.WriteLine("Wating for the client to write.");
while (client.Connected)
{
try
{
int bytesRead = stream.Read(buffer, 0, buffer.Length);
Console.WriteLine("Read {0} bytes from the client.", bytesRead);
string data = Encoding.UTF8.GetString(buffer).Substring(0, bytesRead);
Console.WriteLine("Read the following string from the client: {0}", data);
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to read from a TCP client: {0}", exception.ToString());
break;
}
}
Console.WriteLine("Client disconnected. Removing client.");
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to connect to a TCP client: {0}", exception.ToString());
}
client.Close();
clients.TryRemove(client, out clientListener);
});
clientListener.Start();
clients.TryAdd(client, clientListener);
}
catch (Exception exception)
{
Console.WriteLine("Error while trying to accept a TCP client: {0}", exception.ToString());
}
Console.WriteLine("A client has connected.");
}
});
connectionListener.Start();
}
public void Stop()
{
server.Stop();
connectionListener.Abort();
}
}
}
}
以下是客户端代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WebSocketClient
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Opening up a TcpClient.");
TcpClient client = new TcpClient();
client.Connect("<Remote Hostname>", <RemotePortNumber>);
Console.WriteLine("TcpClient has connected.");
NetworkStream stream = client.GetStream();
bool closed = false;
new Thread(() =>
{
while (!closed)
{
Console.WriteLine("Writing data to the stream.");
byte[] bytes = Encoding.UTF8.GetBytes("Hello, world.");
stream.Write(bytes, 0, bytes.Length);
Thread.Sleep(1000);
}
}).Start();
Console.ReadLine();
closed = true;
}
}
}
那么这里有什么问题?我在Azure虚拟机上托管服务器,我通过设置入站和出站规则打开了我尝试在远程服务器上的Windows防火墙中用作<RemotePortNumber>
的TCP端口,以允许所有流量和在该端口上的计算机之外,我在Azure门户上创建了一个TCP端点,该端点将我的虚拟机主机名的外部端口映射到我的虚拟机的内部专用端口,两者都设置为映射相同的端口号<RemotePortNumber>
以保持一致性。要进行连接,我使用的<Remote Hostname>
值为<MyServiceName>.cloudapp.net
。我也尝试使用IPAddress.Parse(<Public IP of my Azure Server>)
来连接流,但没有运气......它只是保持超时,好像我没有正确格式化主机名或其他东西。我错过了什么?如果有人能提供一些关于如何调试问题的线索,那也会非常有帮助。
更新:运行WireShark跟踪,我看到很多这些消息(这是不是很糟糕?我认为如果考虑到Azure必须路由数据包,TCP重传可能没问题从公共域的端口到VM的私有端口,但不确定RST,ACK是什么):
更新:运行Microsoft Message Analyzer,我在本地链接层看到这些消息:
注意:我的VM的内部IP为100.75.20.78,公共IP为191.238.37.130。它的公共域名是ovidius.cloudapp.net。我正在尝试在TCP端口6490上托管应用程序。为了不放弃,我将我的个人IP地址涂黑了。
我已将Azure门户中的TCP端口从域映射到VM,如下所示:
答案 0 :(得分:3)
在这上面花了两个母亲_______天(填补空白)后,我在探索替代方法方面有点创意,试着看看我是否可以规范路由问题。我可以非常安全地得出结论,当您将公共端口映射到同一个私有端口时,Microsoft的虚拟机路由会失败。
例如,我尝试在下面设置新的Socket端点,它起作用,因为它没有像我之前使用WebSocketServer那样将相同的域端口映射到同一个虚拟机端口:
更新:此外,在托管时,我必须设置服务器,而不是IP 127.0.0.1,而是内部IP,在我的情况下是100.75.20.78。
再次更新:与上述解决方案相反,我尝试在6490删除旧端点并重新创建它,当我现在连接到该地址时,它似乎正在工作。我不完全确定为什么,我只能说这里唯一的区别是我在这次创建端点之前有防火墙规则允许该端点的端口...不确定这是否会产生影响。老实说,我不确定是什么导致了这些问题。
再次更新:只是考虑一下......我认为这可归结为以下两个问题: