1. 程式人生 > >使用unity通過tcp建立聊天室

使用unity通過tcp建立聊天室

1.伺服器端建立

使用while迴圈不斷地接收客戶端的請求,將連線儲存到clientList中

class Program
    {
        static List<Client> clientList = new List<Client>();
        static void Main(string[] args)
        {
            Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.103"),7788));

            tcpServer.Listen(100);
            Console.WriteLine("server Running..");

            while (true)
            {
                Console.WriteLine ("new Client Connected");
                Socket clientSocket = tcpServer.Accept();
                Client client = new Client(clientSocket);//把每個與客戶端通訊的邏輯放到Client類裡面進行處理
                clientList.Add(client);
            }
        }
    }

使用Client類來處理與客戶端通訊的邏輯

class Client
    {
        private Socket clientSocket;
        public Client(Socket s)
        {
            clientSocket = s;
        }
    }

2.客戶端的建立

講這個指令碼放在一個空物體上,客戶端連線伺服器,建立點選事件,再點選的時候獲取輸入框中的文字,傳送給伺服器

public class ChatManager : MonoBehaviour {

    public string ipaddress = "192.168.1.103";
    public int port = 7788;
    public InputField inputField;

    private Socket clientSocket;
	void Start () {
        ConnectToServer();
	}
	void Update () {
		
	}
    void ConnectToServer()
    {
        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
        Debug.Log("send connect");
    }
    void SendMessage(string message)
    {
        byte[] data = Encoding.UTF8.GetBytes(message);
        clientSocket.Send(data);
    }

    public void OnSendButtonClick()
    {
        string value = inputField.text;
        SendMessage(value); 
    }
}

3.客戶端斷開

在客戶端斷開的時候斷開連線

void OnDestroy()
    {
        clientSocket.Shutdown(SocketShutdown.Both);
        clientSocket.Close();//關閉連線    
    }

在伺服器端

使用Poll方法(第一個引數是時間(ms),

模式(SelectMode)

返回(return)

SelectRead

1.  如果已呼叫Listen並且有掛起的連線,則為true。

2.如果有資料可供讀取,則為true。

3.如果連線已關閉、重置或終止,則返回true。

SelectWrite

1.  如果正在處理Connect並且連線已成功,則為true。

2.  如果可以傳送資料,則返回true。

SelectError

1.  如果正在處理不阻止的Connect,並且連線已失敗,則為true。

2.  如果OutOfBandInline未設定,並且帶外資料可用,則為true。

if (clientSocket.Poll(10, SelectMode.SelectRead))
                {
                    Console.WriteLine("連線中斷");
                    break;//終止執行緒執行
                }

4.在伺服器端將資訊分發(廣播)到客戶端

在伺服器端接到訊息的時候呼叫廣播訊息的方法,將訊息進行廣播。使用靜態方法,在廣播的時候,遍歷列表中的連線列表中的全部。並將斷開連線的socket從列表中刪除

Program.BroadcastMessage(message);
 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);
                }
            }
            foreach(var temp in NotConnectedList)
            {
                clientList.Remove(temp);
            }
        }

在客戶端開啟一個執行緒接收來自伺服器端的訊息,在接收訊息的執行緒中,迴圈的接收訊息。

void ConnectToServer()
    {
        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
        Debug.Log("send connect");

        t = new Thread(ReceiveMessage);
        t.Start();
    }

    void ReceiveMessage()
    {
        while (true)
        {
            if(clientSocket.Connected == false)
            {
                break;
            }
            int length = clientSocket.Receive(data);
            message = Encoding.UTF8.GetString(data, 0, length);
        }
    }

在Update中監聽message,如果得到了伺服器傳送過來的訊息,就更新UI中的Text。

void Update () {
		if(message != ""&& message!=null)
        {
            mtext.text += "\n" + message;
            message = "";
        }
	}