您的位置:首页 > 编程语言 > C#

201803041447->初试c#socket聊天室

2018-03-04 15:10 399 查看
目的:利用socket来完成简单多人聊天室

服务端

Program.cs

namespace chatserver

{

    internal class Program

    {

        private static void Main(string[] args)

        {

            Server server = new Server("127.0.0.1", 9404);

            server.Start();

        }

    }

}

Client.cs

internal class Client

    {

        private Server mServer;

        private Socket ClientSocket;

        private bool mClientState;

        private static readonly byte[] ReciveBuffer = new byte[512];//缓冲区

        internal Client(Server server, Socket clientsocket)

        {

            this.mServer = server;

            this.ClientSocket = clientsocket;

            StartReciveSocketData();

        }

        private void StartReciveSocketData()

        {

            mClientState = true;

            Thread thread = new Thread(ReciveMessage);

            thread.IsBackground = true;

            thread.Start();

        }

        private void ReciveMessage()

        {

            int length = -1;

            while (mClientState)

            {

                if (this.ClientSocket.Poll(10, SelectMode.SelectRead))//处理客户端断线

                {

                    Recycle();

                    Console.WriteLine("client connect fail...");

                    break;

                }

                try

                {

                    length = this.ClientSocket.Receive(ReciveBuffer);

                    string message = Encoding.UTF8.GetString(ReciveBuffer, 0, length);

                    SendMessage(message);

                }

                catch (Exception ex)

                {

                    Console.WriteLine(">error : " + ex.ToString());

                }

            }

        }

        private void SendMessage(string message)//广播消息

        {

            if (!string.IsNullOrEmpty(message))

            {

                this.mServer.DispatchMessage(message);

            }

        }

        internal void RealSendMessage(string message)//发送消息

        {

            if (!string.IsNullOrEmpty(message))

            {

                message = this.ClientSocket.GetHashCode() + " > " + message;

                byte[] bytes = Encoding.UTF8.GetBytes(message);

                this.ClientSocket.Send(bytes);

                Console.WriteLine(string.Format(">send {0} message > {1} ", this.ClientSocket.GetHashCode(), message));

            }

        }

        internal void Recycle()//回收

        {

            mClientState = false;

            ClientSocket.Dispose();

            ClientSocket.Close();

        }

        internal bool IsConnected()//判断是否未断线

        {

            return ClientSocket.Connected;

        }

    }

Server.cs

internal class Server

    {

        protected IPEndPoint mIPEndPoint;

        private Socket mServerSocket;//主线程套接字

        private bool mServerState = false;//服务器状态

        protected static List<Client> mClients = new List<Client>();//所有用户

        private static readonly object chatlock = new object();//避免多线程下数据多发

        public Server(string adress, int port)

        {

            IPAddress iPAddress = IPAddress.Parse(adress);

            this.mIPEndPoint = new IPEndPoint(iPAddress, port);

        }

        public Server(int port)

        {

            this.mIPEndPoint = new IPEndPoint(IPAddress.Any, port);

        }

        public void Start()

        {

            mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//新建套接字

            if (this.mIPEndPoint == null)

            {

                Console.WriteLine(">mIPEndPoint nullable...");

                return;

            }

            mServerSocket.Bind(this.mIPEndPoint);//绑定端点

            Console.WriteLine(">Server start...");

            mServerState = true;

            mServerSocket.Listen(10);//开始侦听

            while (mServerState)//死循环,每收到一个用户就专门用一个套接字对象去与用户作沟流

            {

                try

                {

                    Socket clientsocket = mServerSocket.Accept();//accept会阻塞线程,如果没有客户端传入,程序会一直处于假死状态,切记,这里accept只用于学习socket

                    Client client = new Client(this, clientsocket);//将套接字对像传入用户

                    mClients.Add(client);

                }

                catch (Exception)

                {

                    Recycle();

                }

            }

        }

        public void Recycle()//回收

        {

            mServerSocket.Close();

            mServerState = false;

            if (mClients != null && mClients.Any())

            {

                mClients.ForEach(p => p.Recycle());

                mClients.Clear();

            }

            Console.WriteLine("server closed...");

        }

        internal void DispatchMessage(string message)//广播消息并处理已经断线的用户

        {

            lock (chatlock)

            {

                var AllDisConnectedClients = new List<Client>();

                mClients.ForEach(p =>

                {

                    if (p.IsConnected())

                    {

                        p.RealSendMessage(message);

                    }

                    else

                    {

                        //AllDisConnectedClients.Add(p);

                    }

                });

                if (AllDisConnectedClients != null && AllDisConnectedClients.Any())

                {

                    AllDisConnectedClients.ForEach(p =>

                    {

                        p.Recycle();

                    });

                }

            }

        }

    }

客户端,需要自己关联组件

ChatManager.cs

public class ChatManager : MonoBehaviour

{

    private string Message;

    private Thread mThread;

   
4000
private Socket mSocket;

    [SerializeField]

    private Text mText = null;

    [SerializeField]

    private InputField mInputField = null;//输入栏

    [SerializeField]

    private Button mButton = null;

    private static readonly byte[] buffer = new byte[512];

    // Use this for initialization

    private void Awake()

    {

        Application.runInBackground = true;

    }

    private void Start()

    {

        Thread thread = new Thread(InitializationSocket);

        thread.IsBackground = true;

        thread.Start();

        mButton.onClick.AddListener(OnClick);

        mText.text = string.Empty;

    }

    private void InitializationSocket()

    {

        IPAddress address = IPAddress.Parse("127.0.0.1");

        IPEndPoint iPEndPoint = new IPEndPoint(address, 9404);

        mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        try

        {

            mSocket.Connect(iPEndPoint);

        }

        catch (Exception ex)

        {

            Debug.Log(">error : " + ex.ToString());

        }

        mThread = new Thread(ReciveMessage);

        mThread.Start();

    }

    private void ReciveMessage()

    {

        while (true)

        {

            if (mSocket.Connected == false)

            {

                break;

            }

            int length = mSocket.Receive(buffer);

            if (length > 0)

            {

                //lock (Message)//开锁则不能显示信息原因--主线程一直监控message变量,子线程不能调用

                {

                    Message = Encoding.UTF8.GetString(buffer, 0, length);

                    Debug.Log("recive message : " + Message);

                }

            }

        }

    }

    private void OnClick()

    {

        if (mInputField.text != null && mInputField.text != "")

        {

            SendChatMessage(mInputField.text);

            mInputField.text = string.Empty;

        }

    }

    private void SendChatMessage(string text)

    {

        Byte[] texts = Encoding.UTF8.GetBytes(text);

        mSocket.Send(texts);

    }

    // Update is called once per frame

    private void Update()

    {

        if (Input.GetKeyDown(KeyCode.J))

        {

            Debug.Log("this.mThread.IsAlive : " + this.mThread.IsAlive);

            Debug.Log("this.mSocket.Connected : " + this.mSocket.Connected);

        }

        if (Message != null && !string.IsNullOrEmpty(Message))

        {

            mText.text += (Message + "\n");

            Message = string.Empty;

        }

    }

    private void OnDestroy()

    {

        this.mThread.Abort();

        this.mSocket.Shutdown(SocketShutdown.Both);

        this.mSocket.Close();

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c# 心得 理解 笔记