【发布时间】:2020-06-25 15:43:59
【问题描述】:
我有一个基本的 TCP 客户端和服务器都在我的机器上本地运行。
如果我调用 ConnectAsync() 时服务器已经在监听,那么客户端连接到服务器,没问题。
如果我启动客户端并调用 ConnectAsync(),那么在监听客户端之后启动服务器,它不会建立连接。 ConnectAsync 在我收到以下错误之前挂起大约 85 秒: System.Net.Sockets.SocketException (0x80004005): Connection refused。尽管服务器已经开始监听了。
不确定这是否会影响 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");
}
}
【问题讨论】:
-
不是网络专家,但这听起来对我来说是正确的行为。应该很容易使用 telnet 或网络工具进行测试,看看它是否以相同的方式响应。
-
我想这很好(从网络的角度来看)。因此,您可能可以设置短客户端连接超时,但在客户端多次调用
ConnectAsync(检查异常代码\类型并计算连接尝试以打破循环) -
@oleksa 是的,我认为这可能是我必须要做的。烦人的是,TcpClient 的超时时间没有暴露,所以我什至无法设置它。
-
@DavidAndrewThorpe 您可以尝试使用
ConnectAsyncapproach 设置连接“超时”