socket 客户端和服务器通信

发布于:2025-04-18 ⋅ 阅读:(29) ⋅ 点赞:(0)

服务器

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();
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到