c# - TcpClient 仅在服务器在调用 ConnectAsync 之前开始侦听时才连接
问题描述
我有一个基本的 TCP 客户端和服务器都在我的机器上本地运行。
如果在我调用 ConnectAsync() 时服务器已经在监听,那么客户端连接到服务器,没问题。
如果我启动客户端并调用 ConnectAsync(),然后在监听客户端之后启动服务器,它不会建立连接。ConnectAsync 在我收到以下错误之前挂起大约 85 秒: System.Net.Sockets.SocketException (0x80004005): Connection denied。尽管事实上服务器已经开始监听。
不确定这是否会影响 TcpClient,但客户端正在 Xamarin 项目中运行。
这是我的代码:
客户:
public static class DataSource
{
private static TcpClient client;
private static NetworkStream networkStream;
public static bool Connected => client is null ? false : client.Connected;
public static async Task EstablishTcpConnection(string serverIP, int port)
{
CloseTcpConnection();
try
{
client = new TcpClient();
await client.ConnectAsync(IPAddress.Parse(serverIP), port);
networkStream = client.GetStream();
}
catch (Exception ex)
{
Console.WriteLine($"{nameof(EstablishTcpConnection)} Error: {ex}");
}
}
public static void CloseTcpConnection()
{
if (networkStream != null)
{
networkStream.Close();
networkStream.Dispose();
networkStream = null;
}
if (client != null)
{
client.Close();
client.Dispose();
client = null;
}
}
public static async Task SendTcp(string toSend)
{
if (client is null) return;
if (networkStream is null) return;
if (!Connected) return;
if (networkStream != null && networkStream.CanWrite)
{
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(toSend);
await networkStream.WriteAsync(bytesToSend, 0, bytesToSend.Length);
}
}
public static async Task TcpListener()
{
while (networkStream != null && networkStream.CanRead)
{
if (client is null) return;
if (networkStream is null) return;
if (!Connected) return;
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = await networkStream.ReadAsync(bytesToRead, 0, client.ReceiveBufferSize);
string received = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
Console.WriteLine($"Received: {received}");
}
}
}
服务器:
internal class Program
{
private const string serverIP = "MyServerIp";
private const int port = myPort;
private static void Main(string[] args)
{
Listener();
Console.ReadLine();
}
public static async Task Listener()
{
//---listen at the specified IP and port no.---
TcpListener listener = new TcpListener(IPAddress.Parse(serverIP), port);
listener.Start();
Console.WriteLine("Listening...");
while (true)
{
//---incoming client connected---
ReceiveClient(await listener.AcceptTcpClientAsync());
}
}
public static async Task ReceiveClient(TcpClient client)
{
if (client is null) return;
Console.WriteLine("Client Connected");
//---get the incoming data through a network stream---
NetworkStream networkStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
while (client != null && client.Connected)
{
//---read incoming stream---
int bytesRead = await networkStream.ReadAsync(buffer, 0, client.ReceiveBufferSize);
if (bytesRead == 0) break;
//---convert the data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received : " + dataReceived);
//---write back the text to the client---
Console.WriteLine("Sending back : " + dataReceived);
networkStream.Write(buffer, 0, bytesRead);
}
client.Close();
client.Dispose();
Console.WriteLine("Client Disconnected");
}
}
解决方案
即使服务器开始侦听并且在超时范围内,当然 ConnectAsync() 应该仍然有效?
不; 这不是“超时”的意思。“超时”并不意味着“重试”。
当您建立连接时,您的客户端应用程序正在访问在服务器计算机上运行的服务器应用程序。“超时”只是客户端应用程序等待响应的时间量。如果服务器计算机正在运行,但该端口没有侦听服务器应用程序,则服务器计算机将立即发送响应,指示没有服务器应用程序在运行。这将被发送回您的客户端应用程序。这是一个有效的“响应”,因此超时不会起作用。
如果您想重试连接,等待服务器,那么您需要自己编写该逻辑。
推荐阅读
- laravel - 将本地 Laravel 环境连接到 Google Cloud SQL - MySQL
- etl - 如何使用 KSQL 计算 DAU/MAU?
- angular - 我收到类似“无法读取未定义的属性'get'”的错误。如何解决这个问题?
- sql - 查询以显示今天在 postgres 中输入的记录(纪元时间)
- angularjs - $onInit 使用自己的作用域?
- android - 任何处理器都无法识别以下选项:'[kapt.kotlin.generated, room.incremental]'
- svn - 如何在 Windows 10 上将以“-”开头的文件添加到 svn
- php - 安全 URL 是使用 WordPress 返回 ERR_TOO_MANY_REDIRECTS
- python - 是否可以在不迭代\导入 Python 中的所有帧的情况下导入视频的第 #n 帧?
- google-cloud-platform - GCP LoadBalancer - 如何在运行状况检查失败时重定向