1. 程式人生 > >Unity 簡易聊天室(基於TCP)(1)

Unity 簡易聊天室(基於TCP)(1)

為了準備畢業設計,學習了伺服器與客戶端之間傳輸的一些簡單的知識,並跟著網路上的教程製作了一個簡易的Unity聊天室

伺服器:用C# .Net Framework寫的

結構分為:main(主函式)、Server類(用於伺服器的開啟和接收客戶端連線)、Client類(接收訊息和傳送訊息)、Message類(用於訊息的解析和包裝)

 

main:

static void Main(string[] args)
{
  string ip = "127.0.0.1";  //這個ip地址表示本機
  int port = 6688;  //測試用的埠號,應該可以自己隨便寫吧


  Server server = new Server(ip, port);
  server.Start();


  Console.ReadKey();
}

 

 

Server:

public class Server
{
  private Socket serverSocket = null;
  private List<Client> clientList = new List<Client>();
  private Socket clientSocket = null;


  public Server() { }

  public Server(string ip,int port)
  {

         //建立socket,然後繫結ip地址和埠號

    //傳輸型別是流,使用的協議是Tcp
    serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    EndPoint point = new IPEndPoint(IPAddress.Parse(ip), port);
    serverSocket.Bind(point);


  }

  public void Start()
  {
    serverSocket.Listen(0);   //開始監聽  0表示等待連線佇列的最大數
    Console.WriteLine("開始監聽");
    Console.WriteLine("等待客戶端連線");
    serverSocket.BeginAccept(AcceptCallBack, null); //等待客戶端連線,AcceptCallBack是回撥,第三個引數目前還沒用過,沒去了解作用  TODO
  }

  private void AcceptCallBack(IAsyncResult ar)
  {
    clientSocket = serverSocket.EndAccept(ar);
    Console.WriteLine("一個客戶端連線");
    Client client = new Client(clientSocket,this);  //當客戶端連線上後,用Client類處理訊息的接收與傳送
    clientList.Add(client);
    client.Start();//開始接收訊息

    serverSocket.BeginAccept(AcceptCallBack, null);  //伺服器繼續等待其他客戶端連線
  }

  

  public void Broadcast(string message)  //廣播訊息
  {
    foreach(Client client in clientList)
    {
      client.SendMessage(message);
    }
  }
}

 

Client:

 

public class Client
{
  private Socket clientSocket;
  private Server server;
  private Message msg = new Message();

  public Client() { }

  public Client(Socket clientSocket,Server server)
  {
    this.clientSocket = clientSocket;
    this.server = server;
  }


  public void Start()
  {
    //判斷客戶端是否被關閉  
    if (clientSocket.Connected == false || clientSocket.Poll(10, SelectMode.SelectRead))
    {
      clientSocket.Close();
      return;
    }

    //等待從客戶端的訊息的接收
    clientSocket.BeginReceive(msg.data, 0, msg.data.Length, SocketFlags.None, ReceiveCallBack, null);
  }


  private void ReceiveCallBack(IAsyncResult ar)
  {
  try
  {

    //需要用try catch 捕捉異常,不然出現異常伺服器會終止
    //判斷客戶端是否被關閉
    if (clientSocket.Connected==false || clientSocket.Poll(10,SelectMode.SelectRead))
    {
      clientSocket.Close();
      return;
    }

    int len = clientSocket.EndReceive(ar);  //返回的len表示接收的資料長度
    if (len == 0) //客戶端被關閉了 服務端會接收到0位元組的訊息
    {
      clientSocket.Close();
      return;
    }

    msg.Read(len, OnProessMassage);//Message類解析訊息
    //Console.WriteLine("receive:" + message);

    clientSocket.BeginReceive(msg.data, 0, msg.data.Length, SocketFlags.None, ReceiveCallBack, null);
  }
  catch (Exception e)
  {
    Console.WriteLine("ReceiveCallBack:" + e);
  }

  }

 

  private void OnProessMassage(string msg)
  {
    server.Broadcast(msg);//通過伺服器廣播訊息
  }


  public void SendMessage(string message)
  {
    //判斷客戶端是否被關閉  傳送的時候客戶端也可能被關閉
    if (clientSocket.Connected == false || clientSocket.Poll(10, SelectMode.SelectRead))
  {
    clientSocket.Close();
    return;
  }

  clientSocket.Send(msg.Pack(message)); //傳送訊息給客戶端
  //Console.WriteLine("send:"+message);
  }

}

 

Message:

 //這裡只是簡單的處理訊息;解析:從byte[] ->string;傳送:string->byte[]

class Message
{

  public byte[] data = new byte[1024];

  public void Read(int len,Action<string>OnProessMessage)
  {
    string message = Encoding.UTF8.GetString(data, 0, len);
    OnProessMessage(message);
    Array.Clear(data, 0, len);
  }


  public byte[] Pack(string msg)
  {
    byte[] dataBytes = Encoding.UTF8.GetBytes(msg);
    return dataBytes;
  }  

}