使用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 = "";
        }
	}

猜你喜欢

转载自blog.csdn.net/Game_Builder/article/details/81253206