C# Socket消息延迟排查及连接认证实现求助
C# Socket网络程序:消息延迟问题排查与认证机制实现
一、消息接收延迟的原因及修复
问题根源
服务端和客户端的核心逻辑中,外层存在无意义的while (true)循环,每次循环都会重复创建新的Task.Run异步任务处理消息收发。这会导致短时间内生成大量重复后台任务,线程资源被过度抢占,最终引发消息接收的明显延迟。
修复方案
移除外层的while (true)循环,仅启动一次接收和发送任务即可——任务内部已经包含持续处理消息的循环,无需重复创建任务。
二、连接认证机制实现
认证流程
- 客户端连接服务端成功后,立即发送预设的认证凭证
- 服务端接收凭证并与本地存储的凭证比对:
- 验证通过:返回认证成功响应,进入正常消息收发阶段
- 验证失败:返回认证失败响应并主动断开连接
- 客户端根据服务端的响应结果,决定是否继续通信
修改后的完整代码
服务端代码
using System.Net; using System.Net.Sockets; using System.Text; namespace Networking_Experimenting { internal class CustomServer { private IPEndPoint ipEndPoint; private Socket listener; private Socket currentConnection; private readonly string _validAuthToken = "E36"; public CustomServer(string host, int port) { Server(host, port).Wait(); } public async Task Server(string host, int port) { await ServerInit(host, port); await ListenForConnection(); } public async Task ServerInit(string host, int port) { ipEndPoint = new(IPAddress.Parse(host), port); listener = new( ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listener.Bind(ipEndPoint); } private async Task ListenForConnection() { try { listener.Listen(0); Console.WriteLine("Server started listening for connections."); var acceptTask = listener.AcceptAsync(); var delayTask = Task.Delay(TimeSpan.FromMinutes(1)); var completedTask = await Task.WhenAny(acceptTask, delayTask); if (completedTask == acceptTask) { currentConnection = await acceptTask; Console.WriteLine("Connection received."); // 执行认证逻辑 if (!await AuthenticateClient()) { Console.WriteLine("Authentication failed, closing connection."); currentConnection.Dispose(); return; } Console.WriteLine("Client authenticated successfully."); // 仅启动一次收发任务 _ = StartReceivingMessages(); _ = StartSendingMessages(); } else { Console.WriteLine("Server timed out waiting for connection."); } } catch (Exception ex) { Console.WriteLine($"Server error: {ex.Message}"); } finally { listener.Dispose(); } } private async Task<bool> AuthenticateClient() { var buffer = new byte[1024]; var receiveSize = await currentConnection.ReceiveAsync(buffer, SocketFlags.None); var receivedToken = Encoding.UTF8.GetString(buffer, 0, receiveSize).Trim(); var response = receivedToken == _validAuthToken ? "AUTH_SUCCESS" : "AUTH_FAILED"; var responseBytes = Encoding.UTF8.GetBytes(response); await currentConnection.SendAsync(responseBytes, SocketFlags.None); return receivedToken == _validAuthToken; } private async Task StartReceivingMessages() { while (true) { try { var buffer = new byte[1024]; var receiveSize = await currentConnection.ReceiveAsync(buffer, SocketFlags.None); if (receiveSize == 0) { Console.WriteLine("Client disconnected."); currentConnection.Dispose(); break; } var receivedMessage = Encoding.UTF8.GetString(buffer, 0, receiveSize); if (!string.IsNullOrEmpty(receivedMessage)) { Console.WriteLine("Client: " + receivedMessage); } } catch (Exception ex) { Console.WriteLine($"Receive error: {ex.Message}"); break; } } } private async Task StartSendingMessages() { while (true) { try { string message = Console.ReadLine(); if (!string.IsNullOrEmpty(message)) { byte[] encodedMsg = Encoding.UTF8.GetBytes(message); await currentConnection.SendAsync(encodedMsg, SocketFlags.None); } } catch (Exception ex) { Console.WriteLine($"Send error: {ex.Message}"); break; } } } } }
客户端代码
using System.Net; using System.Net.Sockets; using System.Text; namespace Networking_Experimenting { internal class CustomClient { private IPEndPoint ipEndPoint; private Socket client; private readonly string _authToken = "E36"; public CustomClient() { Client().Wait(); } public async Task Client() { await ClientInit(); await StartClient(); } public async Task ClientInit() { ipEndPoint = new(IPAddress.Any, 0); client = new( ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } private async Task StartClient() { Console.WriteLine("Enter the Server IP and port separated by a /"); string[] ipPort; while (true) { ipPort = Console.ReadLine().Split('/', StringSplitOptions.RemoveEmptyEntries); if (ipPort.Length == 2) break; Console.WriteLine("Invalid format! Try again (e.g., 127.0.0.1/8080)"); } var serverIP = IPAddress.Parse(ipPort[0]); var serverPort = int.Parse(ipPort[1]); ipEndPoint = new IPEndPoint(serverIP, serverPort); try { await client.ConnectAsync(ipEndPoint); Console.WriteLine("Connected to server."); // 发送认证凭证并等待结果 if (!await AuthenticateWithServer()) { Console.WriteLine("Authentication failed. Closing connection."); client.Dispose(); return; } Console.WriteLine("Authentication successful. Start messaging:"); // 仅启动一次收发任务 _ = StartReceivingMessages(); _ = StartSendingMessages(); } catch (Exception ex) { Console.WriteLine($"Client error: {ex.Message}"); } } private async Task<bool> AuthenticateWithServer() { var authBytes = Encoding.UTF8.GetBytes(_authToken); await client.SendAsync(authBytes, SocketFlags.None); Console.WriteLine("Authentication token sent."); var buffer = new byte[1024]; var receiveSize = await client.ReceiveAsync(buffer, SocketFlags.None); var response = Encoding.UTF8.GetString(buffer, 0, receiveSize).Trim(); return response == "AUTH_SUCCESS"; } private async Task StartReceivingMessages() { while (true) { try { var buffer = new byte[1024]; var receiveSize = await client.ReceiveAsync(buffer, SocketFlags.None); if (receiveSize == 0) { Console.WriteLine("Server disconnected."); client.Dispose(); break; } var receivedMessage = Encoding.UTF8.GetString(buffer, 0, receiveSize); if (!string.IsNullOrEmpty(receivedMessage)) { Console.WriteLine("Server: " + receivedMessage); } } catch (Exception ex) { Console.WriteLine($"Receive error: {ex.Message}"); break; } } } private async Task StartSendingMessages() { while (true) { try { string message = Console.ReadLine(); if (!string.IsNullOrEmpty(message)) { byte[] encodedMsg = Encoding.UTF8.GetBytes(message); await client.SendAsync(encodedMsg, SocketFlags.None); } } catch (Exception ex) { Console.WriteLine($"Send error: {ex.Message}"); break; } } } } }
内容的提问来源于stack exchange,提问作者kamberoFF
相关产品推荐
相关产品推荐

