Unity 实现socket双向通信

Unity 实现socket通信

实现双向通信,和断线重连

需求场景:有A、B两个unity项目,需要A控制B播放对应的视频。(A点击某按钮,B播放对应的视频)

  1. 服务端

    • 我这边服务端挂载在B项目,随便创建个空物体挂载脚本即可。脚本如下
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;
    using UnityEngine;
    using System.Collections;
    using System.Threading;
    
    public class SocketServer : MonoBehaviour
    {
        private GuidePageController _PlayerManager;
        private TcpListener listener;
        private TcpClient client;
        private NetworkStream stream;
        private SynchronizationContext unityContext;
        [Range(1,65535)][Header("socket通信端口")]
        public int port;
    
        void Start()
        {
            unityContext = SynchronizationContext.Current;
            _PlayerManager = GetComponent<GuidePageController>();
            StartServer();
        }
    
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                GetComponent<SocketServer>().SendWebSocketMessage("Hello from B!");
            }
        }
    
        void StartServer()
        {
            Debug.Log($"Socket Server will start on port {port}");
            listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            Debug.Log($"Socket Server started on port {port}");
            Task.Run(() => AcceptClient());
        }
    
        async void AcceptClient()
        {
            client = await listener.AcceptTcpClientAsync();
            Debug.Log("Client connected");
            stream = client.GetStream();
            await Task.Run(() => ReceiveMessages());
        }
    
        async Task ReceiveMessages()
        {
            byte[] buffer = new byte[1024];
    
            while (client.Connected)
            {
                int byteCount = await stream.ReadAsync(buffer, 0, buffer.Length);
                if (byteCount > 0)
                {
                    string message = Encoding.UTF8.GetString(buffer, 0, byteCount);
                    Debug.Log("Command received: " + message);
                    try
                    {
                        Debug.LogError(unityContext);
                        unityContext.Post(_ => _PlayerManager.SwitchPages(message.Trim()), null);
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError("Error receiving message: " + ex.Message);
                    }
                }
                else
                {
                    Debug.Log("Connection lost.");
                    Task.Run(() => AcceptClient());  // 尝试重新开始监听
                    break;
                }
            }
        }
    
        public async void SendWebSocketMessage(string message)
        {
            if (client != null && client.Connected)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                await stream.WriteAsync(buffer, 0, buffer.Length);
                Debug.Log("Sent: " + message);
            }
        }
    
        void OnDestroy()
        {
            CloseConnection();
        }
    
        private void CloseConnection()
        {
            listener?.Stop();
            if (client != null)
            {
                client.Close();
                client = null;
            }
    
            if (stream != null)
            {
                stream.Close();
                stream = null;
            }
        }
    }
    
    • 这段代码为接收消息后进行的操作,自定义即可
    _PlayerManager.SwitchPages(message.Trim()
    
  2. 客户端

    • 客户端挂载在A项目
    using System;
    using System.Collections.Generic;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;
    using UnityEngine;
    
    public class SocketClient : MonoBehaviour
    {
    
        [Header("Socket连接的IP及端口")]
        public string Address;
        public int Port;
        
        private TcpClient client;
        private NetworkStream stream;
        private int _waitTime = 5000;
        private SocketClient _socketClient;
        
        private Dictionary<KeyCode, string> _keyMap;
       
    
        void Start()
        {
            _socketClient = GetComponent<SocketClient>();
            ConnectToServer();
            
            _keyMap = new Dictionary<KeyCode, string>
            {
                { KeyCode.Alpha1, "1" },
                { KeyCode.Alpha2, "2" },
                { KeyCode.Alpha3, "3" },
                { KeyCode.Alpha4, "4" },
                { KeyCode.Alpha5, "5" },
                { KeyCode.Alpha6, "6" },
                { KeyCode.Alpha7, "7" },
                { KeyCode.Alpha8, "8" },
                { KeyCode.Alpha9, "9" },
                { KeyCode.Alpha0, "0" },
                { KeyCode.Space, "space" },
                { KeyCode.LeftArrow, "left arrow" },
                { KeyCode.RightArrow, "right arrow" }
            };
            
        }
    
        void Update()
        {
            foreach (var keyCode in _keyMap.Keys)
            {
                if (Input.GetKeyDown(keyCode))
                {
                    string keyString = _keyMap[keyCode];
                    _socketClient.SendWebSocketMessage(keyString);
                    break;
                }
            }
        }
    
    
        async Task ConnectToServer()
        {
            Debug.Log("尝试建立通信");
            try
            {
                client = new TcpClient();
                await client.ConnectAsync(Address, Port);  // 连接到B项目的服务器
                Debug.Log("Connected to server");
                stream = client.GetStream();
    
                // 开始监听消息
                _ = Task.Run(() => ReceiveMessages());
            }
            catch (Exception ex)
            {
                Debug.LogError("Error connecting to server: " + ex.Message);
                await Task.Delay(_waitTime); 
                await ConnectToServer();
            }
        }
    
        async void ReceiveMessages()
        {
            byte[] buffer = new byte[1024];
            while (client.Connected)
            {
              
                int byteCount = await stream.ReadAsync(buffer, 0, buffer.Length);
                if (byteCount > 0)
                {
                    string message = Encoding.UTF8.GetString(buffer, 0, byteCount);
                    Debug.Log("Received: " + message);
                    // 根据接收到的消息进行不同的处理
                }
                else
                {
                    print("--------通信中断--------");
                    CloseConnection();
      		   await Task.Delay(_waitTime);   // 等待后再开始重连
                    await ConnectToServer();
     	   break;
                }
            }
        }
    
        public async void SendWebSocketMessage(string message)
        {
            if (client != null && client.Connected)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                await stream.WriteAsync(buffer, 0, buffer.Length);
                Debug.Log("Sent: " + message);
            }
        }
    
        void OnDestroy()
        {
            CloseConnection();
        }
        
        private void CloseConnection()
        {
            if (client != null)
            {
                client.Close();
                client = null;
            }
    
            if (stream != null)
            {
                stream.Close();
                stream = null;
            }
        }
    }
    
    • 使用A向B发送消息
      FindFirstObjectByType<SocketClient>().SendWebSocketMessage("111111");
    

附图一张
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值