几乎可以肯定,问题在于您在构建服务器时使用了IPAddress.Any。这是一个问题的原因是因为这不一定会解决localhost,尽管你可能很幸运,但它并不一致。因此,我建议使用这样的 IP 地址启动服务器:
var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, clientPort);
接下来,尽管我确信您正在这样做,但请确保 clientPort 和 serverPort 的端口相同。
接下来,while (true) 循环对我来说非常可疑,因此在下面的示例中,我将对其进行更改。除非不可能总是避开while (true),否则你实际上是在乞求问题。
最后,围绕如何在这里进行线程处理,您将需要以某种方式构建两个单独的线程,我将推荐BackgroundWorker 类(其他人可能会推荐async-await,但我不知道还不够推荐和你需要使用 .NET 4.5,我不知道你是不是)。
因此,您可以为服务器构建一个这样的BackgroundWorker(您可以为客户端构建另一个类似的):
var worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.ProgressChanged += (s, args) =>
{
Console.WriteLine(args.UserState);
}
worker.DoWork += (s, args) =>
{
// startup the server on localhost
var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, clientPort);
server.Start();
while (!worker.CancellationPending)
{
// as long as we're not pending a cancellation, let's keep accepting requests
TcpClient client = server.AcceptTcpClient();
StreamReader clientIn = new StreamReader(client.GetStream());
StreamWriter clientOut = new StreamWriter(client.GetStream());
clientOut.AutoFlush = true;
while ((string msg = clientIn.ReadLine()) != null)
{
worker.ReportProgress(1, msg); // this will fire the ProgressChanged event
clientOut.WriteLine(msg);
}
}
}
最后,您需要在某个地方通过调用RunWorkerAsync 来启动这些工作程序,如下所示:
worker.RunWorkerAsync();
更新
好的,下面是连接到 2104 的完全正常工作的控制台应用程序。您需要注意的一件事是,当使用 var ipAddress = Dns.GetHostEntry("localhost").AddressList[0]; 时,我们得到的 IP 地址类似于 ::1,这就是问题所在。但是,如果我们在 127.0.0.1:2104 上进行监听,则客户端能够连接,因为这是在发出 var result = client.BeginConnect("localhost", 2104, null, null); 时它试图连接的内容,这与发出 new TcpClient("localhost", 2104); 相同。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.ComponentModel;
using System.Threading;
using System.Net;
namespace ConsoleApplication13
{
class Program
{
static void Main()
{
var worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.ProgressChanged += (s, args) =>
{
Console.WriteLine(args.UserState);
};
worker.DoWork += (s, args) =>
{
// startup the server on localhost
var ipAddress = IPAddress.Parse("127.0.0.1");
TcpListener server = new TcpListener(ipAddress, 2104);
server.Start();
while (!worker.CancellationPending)
{
Console.WriteLine("The server is waiting on {0}:2104...", ipAddress.ToString());
// as long as we're not pending a cancellation, let's keep accepting requests
TcpClient attachedClient = server.AcceptTcpClient();
StreamReader clientIn = new StreamReader(attachedClient.GetStream());
StreamWriter clientOut = new StreamWriter(attachedClient.GetStream());
clientOut.AutoFlush = true;
string msg;
while ((msg = clientIn.ReadLine()) != null)
{
Console.WriteLine("The server received: {0}", msg);
clientOut.WriteLine(string.Format("The server replied with: {0}", msg));
}
}
};
worker.RunWorkerAsync();
Console.WriteLine("Attempting to establish a connection to the server...");
TcpClient client = new TcpClient();
for (int i = 0; i < 3; i++)
{
var result = client.BeginConnect("localhost", 2104, null, null);
// give the client 5 seconds to connect
result.AsyncWaitHandle.WaitOne(5000);
if (!client.Connected)
{
try { client.EndConnect(result); }
catch (SocketException) { }
string message = "There was an error connecting to the server ... {0}";
if (i == 2) { Console.WriteLine(message, "aborting"); }
else { Console.WriteLine(message, "retrying"); }
continue;
}
break;
}
if (client.Connected)
{
Console.WriteLine("The client is connected to the server...");
StreamReader clientIn = new StreamReader(client.GetStream());
StreamWriter clientOut = new StreamWriter(client.GetStream());
clientOut.AutoFlush = true;
string key;
while ((key = Console.ReadLine()) != string.Empty)
{
clientOut.WriteLine(key);
Console.WriteLine(clientIn.ReadLine());
}
}
else { Console.ReadKey(); }
}
}
}