unity简单的聊天socket编程

最近开始自学socket编程,从网上找不到好的教程,索性搬了个梯只,

刚开始学习,水平有限,见谅

 

窗口布局

 

Asset

unity简单的聊天socket编程_第1张图片

这里我们既当Server也当Client,所以把两个代码都加载上,放到Server这个空GameObject上

 

unity简单的聊天socket编程_第2张图片

这里聊天信息弹出的思路是在chatWindows上加上

unity简单的聊天socket编程_第3张图片

然后接受到聊天信息之后将data放到asset下的prefab里实例化到chatWindows的子物体上,有一个自动排版在里面。

 

然后就是代码部分了

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System;
using System.IO;

public class Server : MonoBehaviour {
    private List clients;   //所有的客户端的集合
    private List disconnectList;   //掉线的客户端的集合

    public int port = 6321;   //端口
    private TcpListener server;   //定义一个端口监听对象
    private bool serverStarted;    //判断服务器是否开启的判断值

    private void Start()
    {
        clients = new List();
        disconnectList = new List();  

        try
        {
            server = new TcpListener(IPAddress.Any, port);
            server.Start(); //应该是一个类似线程的东西,个人感觉TcpListener本身就包含了一个线程

            StartListening();   //开始监听
            serverStarted = true;
            Debug.Log("Server has been started on port" + port.ToString());
        }
        catch (Exception ex)
        {
            Debug.Log("Socket error:"+ex.Message);
        }
    }
    private void Update()
    {
        if (!serverStarted)
            return;

        foreach (ServerClient c in clients)
        {
            //客户端是否仍然在线?
            if (!IsConnected(c.tcp))
            {
                c.tcp.Close();
                disconnectList.Add(c);
                continue;
            }
            //检查客户端发送过来的数据
            else
            {
                NetworkStream s = c.tcp.GetStream();
                if (s.DataAvailable)
                {
                    StreamReader reader = new StreamReader(s, true);
                    string data = reader.ReadLine();

                    if (data != null)
                        OnIncomingData(c, data);   //对数据的回调函数
                }
            }
        }
        for (int i = 0; i < disconnectList.Count - 1; i++)
        {
            Broadcast(disconnectList[i].clientName + " has disconnected !",clients);
            clients.Remove(disconnectList[i]);
            disconnectList.RemoveAt(i);
        }
    }

    private void OnIncomingData(ServerClient c, string data)
    {
        if (data.Contains("%NAME"))   //第一次握手,得到一个包含%NAME|[clientName]的字符串
        {
            c.clientName = data.Split('|')[1];   //通过|将客户端的名字单独分割出来
            Broadcast(c.clientName + " has connected !",clients);  //广播
            return;  //握手完了还没开始聊天,先结束掉
        }
        Broadcast(c.clientName+" : "+data,clients); //握手之后开始广播发送的聊天信息
    }

    private void StartListening()
    {
        server.BeginAcceptTcpClient(AcceptTcpClient,server);
    }
    private bool IsConnected(TcpClient c)
    {
        try
        {
            if (c != null && c.Client != null && c.Client.Connected)
            {
                if (c.Client.Poll(0, SelectMode.SelectRead))
                {
                    return !(c.Client.Receive(new byte[1],SocketFlags.Peek)==0);
                }
                return true;
            }
            else
                return false;
        }
        catch
        {
            return false;
        }
    }    //检查是否仍然在线
    private void AcceptTcpClient(IAsyncResult ar)
    {
        TcpListener listener = (TcpListener)ar.AsyncState;

        clients.Add(new ServerClient(listener.EndAcceptTcpClient(ar)));
        StartListening();

        //Send a message to everyone,say someone has connected
        Broadcast("%NAME",new List() { clients[clients.Count-1]});
    }
    private void Broadcast(string data, List cl)
    {
        foreach (ServerClient c in cl)
        {
            try
            {
                StreamWriter writer = new StreamWriter(c.tcp.GetStream());
                writer.WriteLine(data);   //
                writer.Flush();   //应该是清楚writer的buffer,将数据发送出去
            }
            catch (Exception e)
            {
                Debug.Log("Write error :" + e.Message + "to client" + c.clientName);
            }
        }
    }
}
public class ServerClient
{
    public TcpClient tcp;
    public string clientName;
    public ServerClient(TcpClient clientSocket)
    {
        clientName = "Guest";
        tcp = clientSocket;   //连接上
    }
}

 

 

 

 

 

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using UnityEngine;
using UnityEngine.UI;

public class Client : MonoBehaviour {
    public GameObject chatContainer;
    public GameObject messagePrefab;

    public string clientName;

    private bool socketReady;
    private TcpClient socket;
    private NetworkStream stream;
    private StreamWriter writer;
    private StreamReader reader;

    public void ConnectToServer()
    {
        #region already connected,ignore this function
        if (socketReady)
            return;
#endregion

        #region Default host / port values
        string host = "127.0.0.1";
        int port = 6321;
        #endregion
        #region Overwrite default host / port values,if there is something in those boxes
        string h;
        int p;
        h = GameObject.Find("HostInput").GetComponent().text;
        if (h != "")
            host = h;
        int.TryParse(GameObject.Find("PortInput").GetComponent().text,out p);
        if (p != 0)
            port = p;
        #endregion
        //Create the socket
        try
        {
            socket = new TcpClient(host, port); 
            stream = socket.GetStream();       //得到socket中获取到的数据流
            writer = new StreamWriter(stream);
            reader = new StreamReader(stream);  //初始化读和写
            socketReady = true;
        }
        catch(Exception e)
        {
            Debug.Log("Socket error:" + e.Message);
        }
    }
    private void OnIncomingData(string data)
    {
        if (data == "%NAME")     //(第一次)如果接受到的信息是%NAME,之后接受到的信息将不再含有%NAME
        {
            Send("%NAME|" + clientName);  //将收到的信息"%NAME"转换成 "%NAME|[clientName]" 
            return;
        }
        GameObject go = Instantiate(messagePrefab, chatContainer.transform)as GameObject;
        go.GetComponentInChildren().text = data;   //将接受到的聊天信息打印出来
    }
    private void Send(string data)
    {
        if (!socketReady)
            return;
        writer.WriteLine(data);
        writer.Flush();
    }
    public void OnSendButton()
    {
        string message = GameObject.Find("SendInput").GetComponent().text;
        Send(message);
    }   //点击按钮的回调函数
    private void Update()
    {
        if (socketReady)
        {
            if (stream.DataAvailable)
            {
                string data = reader.ReadLine();
                if (data != null)
                    OnIncomingData(data);
            }
        }
    }

    private void CloseSocket()
    {
        if (!socketReady)
            return;

        writer.Close();
        reader.Close();
        socket.Close();
        socketReady = false;
    }
    private void OnApplicationQuit()   //游戏退出时的回调函数
    {
        CloseSocket();
    }
    private void OnDisable()
    {
        CloseSocket();
    }
}

 

 

 

 

 

运行结果

 

 

 

unity简单的聊天socket编程_第4张图片

 

 

 

你可能感兴趣的:(Unity3D)