socket 客户端和服务器通信
服务器
using BarrageGrab;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;namespace Lyx {class Server{private TcpListener listener;private ConcurrentDictionary<TcpClient, DateTime> clients = new ConcurrentDictionary<TcpClient, DateTime>();private CancellationTokenSource cts = new CancellationTokenSource();public void Start(int port){listener = new TcpListener(IPAddress.Any, port);listener.Start();Console.WriteLine($"服务器已启动,监听端口 {port}...");new Thread(AcceptClients) { IsBackground = true }.Start();new Thread(CheckHeartbeats) { IsBackground = true }.Start();new Thread(HandleConsoleInput) { IsBackground = true }.Start();}private void AcceptClients(){try{while (!cts.Token.IsCancellationRequested){TcpClient client = listener.AcceptTcpClient();Console.WriteLine("新客户端连接:" + client.Client.RemoteEndPoint);clients.TryAdd(client, DateTime.Now);new Thread(() => HandleClient(client)) { IsBackground = true }.Start();}}catch (SocketException) { } // 监听器被停止时正常退出}private void HandleClient(TcpClient client){NetworkStream stream = null;try{stream = client.GetStream();byte[] buffer = new byte[1024];while (!cts.Token.IsCancellationRequested){int bytesRead;lock (client) // 同步网络流访问{if (!stream.DataAvailable){Thread.Sleep(100);continue;}bytesRead = stream.Read(buffer, 0, buffer.Length);}if (bytesRead <= 0) break;string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到消息: {message}");if (message == "heartbeat"){clients.AddOrUpdate(client, DateTime.Now, (_, __) => DateTime.Now);SendMessage(client, "heartbeat");Logger.PrintColor($"服务器发送心跳: {message} ,给客户端成功:{client.Client.RemoteEndPoint}", ConsoleColor.Yellow);continue;}//SendMessage(client, "服务器收到: " + message);}}catch (Exception ex) { Console.WriteLine($"客户端错误: {ex.Message}"); }finally{if (client.Connected ){Console.WriteLine("客户端断开:" + client.Client.RemoteEndPoint);clients.TryRemove(client, out _);client.Close();stream?.Close();}}}public void BroadcastMessage(string message){byte[] data = Encoding.UTF8.GetBytes("服务器广播: " + message);foreach (var client in clients.Keys.ToArray()){try{lock (client){client.GetStream().Write(data, 0, data.Length);}}catch { }}Console.WriteLine("广播消息已发送");}public void SendMessage(TcpClient client, string message){if (!clients.ContainsKey(client)) return;byte[] data = Encoding.UTF8.GetBytes(message);try{lock (client) // 同步网络流访问{client.GetStream().Write(data, 0, data.Length);}Console.WriteLine($"消息发送成功 -> {client.Client.RemoteEndPoint}: {message}");}catch{Console.WriteLine("消息发送失败");}}private void HandleConsoleInput(){while (!cts.Token.IsCancellationRequested){string input = Console.ReadLine();if (input?.ToLower() == "exit"){Stop();break;}else if (!string.IsNullOrWhiteSpace(input)){BroadcastMessage(input);}}}private void CheckHeartbeats(){while (!cts.Token.IsCancellationRequested){Thread.Sleep(5000);DateTime now = DateTime.Now;foreach (var client in clients.Keys.ToArray()){if (clients.TryGetValue(client, out DateTime last) &&(now - last).TotalSeconds > 10){Console.WriteLine("客户端超时断开:" + client.Client.RemoteEndPoint);clients.TryRemove(client, out _);client.Close();}}}}public void Stop(){cts.Cancel();listener.Stop();foreach (var client in clients.Keys.ToArray()){client.Close();clients.TryRemove(client, out _);}Console.WriteLine("服务器已停止");}public void Main(){Server server = new Server();server.Start(54621);}}}
客户端
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;public class SocketClient : MonoBehaviour
{private TcpClient client;private NetworkStream stream;private Thread receiveThread;private bool isConnected = false;private string serverIP = "127.0.0.1"; // 服务器IP地址private int serverPort = 54621; // 服务器端口private float heartbeatTimeout = 5f; // 心跳超时时间private float heartbeatInterval = 0.5f; // 心跳发送间隔时间private float lastHeartbeatTime;private float lastSendHeartbeatTime;private bool updateHeartbeat = false; // 标志位,用于通知主线程更新心跳时间private int reconnectAttempts = 0; // 重连尝试次数private const int maxReconnectAttempts = 3; // 最大重连次数private const float reconnectInterval = 2f; // 重连间隔时间void Start(){ConnectToServer();}void Update(){// 检查是否需要更新心跳时间if (updateHeartbeat){lastHeartbeatTime = Time.time;updateHeartbeat = false;}// 检查心跳超时if (isConnected && Time.time - lastHeartbeatTime > heartbeatTimeout){Debug.Log("Heartbeat timeout, disconnecting...");Disconnect();}// 定时发送心跳消息if (isConnected && Time.time - lastSendHeartbeatTime > heartbeatInterval){SendData("heartbeat");lastSendHeartbeatTime = Time.time;}}void ConnectToServer(){try{client = new TcpClient(serverIP, serverPort);stream = client.GetStream();isConnected = true;lastHeartbeatTime = Time.time;lastSendHeartbeatTime = Time.time;reconnectAttempts = 0; // 重置重连尝试次数receiveThread = new Thread(new ThreadStart(ReceiveData));receiveThread.IsBackground = true;receiveThread.Start();Debug.Log("Connected to server.");}catch (Exception e){Debug.LogError("Error connecting to server: " + e.Message);TryReconnect();}}void ReceiveData(){byte[] buffer = new byte[1024];while (isConnected){try{int bytesRead = stream.Read(buffer, 0, buffer.Length);if (bytesRead > 0){string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);if (receivedMessage != null){Debug.Log("Received from server: " + receivedMessage);// 如果是心跳响应,通知主线程更新心跳时间if (receivedMessage.Equals("heartbeat")){updateHeartbeat = true;}}}}catch (Exception e){Debug.LogError("Error receiving data: " + e.Message);Disconnect();break;}}}public void SendData(string message){if (isConnected){try{byte[] data = Encoding.UTF8.GetBytes(message);stream.Write(data, 0, data.Length);Debug.Log("Sent to server: " + message);}catch (Exception e){Debug.LogError("Error sending data: " + e.Message);Disconnect();}}}void Disconnect(){if (isConnected){isConnected = false;if (receiveThread != null && receiveThread.IsAlive)receiveThread.Abort();if (stream != null)stream.Close();if (client != null)client.Close();Debug.Log("Disconnected from server.");// 尝试重连TryReconnect();}}void TryReconnect(){Debug.Log("触发重连机制");if (reconnectAttempts < maxReconnectAttempts){reconnectAttempts++;Debug.Log($"Attempting to reconnect ({reconnectAttempts}/{maxReconnectAttempts})...");Invoke("ConnectToServer", reconnectInterval); // 2秒后重连}else{Debug.Log("Max reconnection attempts reached. Giving up.");}}void OnDestroy(){Disconnect();}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dtcms.com/a/136339.html
如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!