1. 程式人生 > >Unity聊天室Tcp協議

Unity聊天室Tcp協議

客戶端unity指令碼

using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;

public class UIManager : MonoBehaviour {

    private string ipaddress = "192.168.3.35";
    private int port = 7788;
    private Thread t;       //建立一個執行緒方便管理
    private byte[] data = new byte[1024];
    private string message = "";//Text用來接收Message的容器

    public Text text;       //聊天框
    public InputField textInput;    //輸入框
    
    private Socket clientSocket;
	// Use this for initialization
	void Start () {
        ConnectedToServer();
	}
	
	// Update is called once per frame
	void Update () {
        if (message!=null&&message!="")
        {
            text.text += "\n" + message;
            message = "";//清空訊息
        }
	}

    //和伺服器連線的方法
    private void ConnectedToServer()
    {
        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //發起連線
        clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));

        //建立一個執行緒用來接收訊息
        t = new Thread(ReceiveMeage);
        t.Start();

    }

    /// <summary>
    /// 用來迴圈接收訊息
    /// </summary>
    void ReceiveMeage()
    {
        while (true)
        {
            //判斷是否和伺服器連線
            if (clientSocket.Connected==false)
            {
                break;
            }
            int length = clientSocket.Receive(data);
            message = Encoding.UTF8.GetString(data, 0, length);
            //text.text += "\n" + message;    //unity不允許單獨的執行緒操縱unity元件
        }
        
    }

    //UI介面傳送按鈕的方法
    public void SendMessage(string message)
    {
        //字串轉成位元組陣列
        byte[] data = Encoding.UTF8.GetBytes(message);
        clientSocket.Send(data);    //傳送到伺服器端

    }

    //當按鈕點選的時候獲取文字框內的資訊
    public void OnSendButtonClick()
    {
        string value = textInput.text;  //得到文字框內的內容
        SendMessage(value);
        //傳送完輸入框為空
        textInput.text = "";
    }

    //防止客戶端斷開連線伺服器一直接收訊息
    private void OnDestroy()
    {
        clientSocket.Shutdown(SocketShutdown.Both);
        clientSocket.Close();//關閉連線
    }

}

伺服器端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using 聊天室伺服器端_tcp;

namespace 聊天室伺服器端
{
    /// <summary>
    /// 用來跟客戶端做通訊
    /// </summary>
    class Client
    {
        private Socket clientSocket;
        private Thread t;       //方便管理執行緒
        private byte[] data = new byte[1024];//資料容器,方便頻繁呼叫


        public Client(Socket s)
        {
            clientSocket = s;

            //啟動一個執行緒 處理客戶端的資料接收
            t = new Thread(ReceiveMessage);
            t.Start();
            
        }

        private void ReceiveMessage()
        {
            //一直接收客戶端的資料
            while (true)
            {
                //在接收資料之前,判斷一下Socket是否斷開
                if (clientSocket.Poll(10, SelectMode.SelectRead))//判斷客戶端是否斷開連線
                {
                    clientSocket.Close();
                    break;//跳出迴圈 終止執行緒
                }
                //當客戶端斷開連線時會一直接收訊息,所以要在客戶端做處理

                int length = clientSocket.Receive(data);
                string message = Encoding.UTF8.GetString(data, 0, length);
                //伺服器接收到資料,要把這個資料分發到客戶端
                //廣播這個訊息
                Program.BroadCastMessage(message);

                Console.WriteLine("收到了訊息" + message);
            }

        }

        //--------------向多個客戶端傳送訊息------------------------
        /// <summary>
        /// 傳送方法
        /// </summary>
        /// <param name="message"></param>
        public void SendMessage(string message)
        {
            byte[] data = Encoding.UTF8.GetBytes(message);
            clientSocket.Send(data);

        }
        /// <summary>
        /// 判斷是否和客戶端斷開連線
        /// </summary>
        public bool Connected
        {
            get { return clientSocket.Connected; }//返回這個Socket是否斷開連線
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using 聊天室伺服器端;
/// <summary>
/// 伺服器端
/// </summary>
namespace 聊天室伺服器端_tcp
{
    class Program
    {
        //建立一個空的集合存放連線過來的client物件,就可以知道伺服器和哪些客戶端建立了連線
        static List<Client> clientList = new List<Client>();

        /// <summary>
        /// 廣播訊息分發到各個客戶端
        /// </summary>
        public static void BroadCastMessage(string message)
        {
            var notConnectedList = new List<Client>();//存放斷開連線的客戶端

            foreach (var client in clientList)
            {
                if(client.Connected)    //客戶端在連線狀態
                client.SendMessage(message);
                else
                {
                    //斷開連線的客戶端放到這個集合
                    notConnectedList.Add(client);
                }

            }

            //把斷開連線的客戶端從clientList中移除掉
            foreach (var temp in notConnectedList)
            {
                clientList.Remove(temp);//移除
            }

        }

        static void Main(string[] args)
        {
            Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.3.35"),7788));

            tcpServer.Listen(100);

            Console.WriteLine("伺服器連線成功");
            //--------------接收多個連線---------------
            while (true)
            {
                Socket clientSocket = tcpServer.Accept();
                Console.WriteLine("一個客戶端連線過來");

                Client client = new Client(clientSocket);//把收發訊息的邏輯放到Client類裡處理
                clientList.Add(client);

            }
           


        }
    }
}