Socket群聊 简易


Socket服务器端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SocketServer
{
    class Program
    {
        //服务器商所有客户端列表 
        public static List<Client> users = new List<Client>();
        static void Main(string[] args)
        {
            new Server();
        }
    }

    //服务器类
    class Server
    {
        //声明socket对象
        private Socket socket;
        public Server()
        {
            //第一步,建立Socket对象(ipv4,数据流形式,TCP协议)
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //转化IP地址
            IPAddress ipadress = IPAddress.Parse("0.0.0.0");
            //绑定端口,提供服务
            socket.Bind(new IPEndPoint(ipadress, 9999));

            try
            {
                //开始监听
                socket.Listen(60);
                Console.WriteLine("服务器启动成功");

            }catch(Exception ex)
            {
                Console.WriteLine("服务器启动失败"+ex.Message);
            }

            //开始循环等待用户连接
            while (true)
            {
                //接受客户端连接
                Socket client = socket.Accept();

                //将新客户端对象,存储到列表中
                Program.users.Add(new Client(client)); 
               
                Console.WriteLine("有客户端连接了"+client.RemoteEndPoint.ToString());





                //构建消息主体
                byte[] msgBody = Encoding.UTF8.GetBytes("欢迎来到聊天室,请文明礼貌用语!");

                //构建消息整体
                byte[] msgByte = new byte[4 + 4 + msgBody.Length];

                //消息标识字节数组
                byte[] idbytes = BitConverter.GetBytes(2);

                //消息长度字节数组
                byte[] lenbytes = BitConverter.GetBytes(msgBody.Length);


                //复制字节到指定数组
                Array.Copy(idbytes, msgByte, 4);
                //从指定数组指定位置,复制到另一数组指定位置,指定长度
                Array.Copy(lenbytes, 0, msgByte, 4, lenbytes.Length);
                Array.Copy(msgBody, 0, msgByte, 8, msgBody.Length);

                //向客户端发送消息
                client.Send(msgByte);

                //断开连接
                //socket.Close();
            }


        }
    }
    class Client
    {
        /// <summary>
        /// 连接
        /// </summary>
        private Socket socket;
        /// <summary>
        /// 线程
        /// </summary>
        private Thread thread;

        private byte[] buffers = new byte[2048];
        public Client(Socket sk)
        {
            this.socket = sk;

            //添加线程,处理消息接收
            thread = new Thread(ReceiveData);

            thread.IsBackground = true;
            //启动线程
            thread.Start();
        }

        private void ReceiveData()
        {
            while (true)
            {
                try
                {
                    //将收到数据,存在在缓存里,并获取长度len
                    int len = socket.Receive(buffers);

                    if (len > 8)
                    {
                        //解析标识
                        byte[] idbytes = new byte[4];
                        Array.Copy(buffers, 0, idbytes, 0, 4);
                        //还原消息标识
                        int msgId = BitConverter.ToInt32(idbytes, 0);


                        //消息长度
                        byte[] lenbytes = new byte[4];
                        Array.Copy(buffers, 4, lenbytes, 0, 4);
                        //还原消息长度
                        int msgLen = BitConverter.ToInt32(lenbytes, 0);


                        //消息主体
                        byte[] bodybytes = new byte[msgLen];
                        Array.Copy(buffers, 8, bodybytes, 0, msgLen);
                        //将消息主体还原成字符串
                        string msgBody = Encoding.UTF8.GetString(bodybytes);

                        //控制台输出
                        Console.WriteLine("id={0},len={1},body={2}", msgId, msgLen, msgBody);

                        switch (msgId)
                        {
                            case 1: //公聊消息

                                //获取收到的整个消息字节数组
                                byte[] tmpbytes = new byte[4 + 4 + msgLen];
                                Array.Copy(buffers, tmpbytes, tmpbytes.Length);

                                //遍历用户,进行转发
                                foreach (Client item in Program.users)
                                {
                                    item.Send(tmpbytes);
                                }
                                break;
                        }


                    }

                    /* //还原收到的内容
                     string msg = Encoding.UTF8.GetString(buffers, 0, len);

                     //将这个消息发送给所有客户端
                     foreach (Client item in Program.users)
                     {
                         //发送消息
                         item.Send(msg);
                     }

                     Console.WriteLine(Encoding.UTF8.GetString(buffers, 0, len));
                     */
                }
                catch (Exception ex)
                {
                    Console.WriteLine("客户端" + socket.RemoteEndPoint.ToString() + "掉线了");

                    //掉线后,把自己从列表中删除掉
                    Program.users.Remove(this);
                    //关闭连接
                    socket.Close();
                    //关闭线程
                    thread.Abort();

                }

            }

        }


        /// <summary>
        /// 发送消息方法
        /// </summary>
        /// <param name="msg"></param>
        public void Send(string msg)
        {
            socket.Send(Encoding.UTF8.GetBytes(msg));
        }

        /// <summary>
        /// 发送字节数组
        /// </summary>
        /// <param name="bytes"></param>

        public void Send(byte[] bytes)
        {
            socket.Send(bytes);
        }
    }
}

客户端代码

/*
 *Copyright(C) 2015 by #COMPANY# 
 *All rights reserved. 
 *FileName:     #SCRIPTFULLNAME# 
 *Author:       #AUTHOR# 
 *Version:      #VERSION# 
 *UnityVersion:#UNITYVERSION# 
 *Date:         #DATE#  
*/
using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using UnityEngine.UI;
using System;

public class ChatRoom : MonoBehaviour {
    private Socket socket;

    //定义缓存数组长度
    private byte[] buffers = new byte[2048];

    //开启线程,用来处理数据接收
    private Thread thread;

    //接收到的消息对象
    public struct MsgData
    {
        public int id;
        public string msg;
    }
    //消息队列
    public Queue<MsgData> msgQueue = new Queue<MsgData>();

    //消息文本框 
    public Msg txtMsg;

    //消息发送文本和按钮 
    public InputField inputMsg;
    public Button btnSend;
    // Use this for initialization  
    void Start()
    {

        //获取消息文本框 
        txtMsg = this.transform.Find("msg").GetComponent<Msg>();
        inputMsg = this.transform.Find("input").GetComponent<InputField>();
        btnSend = this.transform.Find("btnSend").GetComponent<Button>();

        //按钮点击 ,发送消息
        btnSend.onClick.AddListener(delegate () {


            //构建消息主体
            byte[] msgBody = Encoding.UTF8.GetBytes(inputMsg.text.Trim());

            //构建消息整体
            byte[] msgByte = new byte[4 + 4 + msgBody.Length];

            //消息标识字节数组
            byte[] idbytes = BitConverter.GetBytes(1);

            //消息长度字节数组
            byte[] lenbytes = BitConverter.GetBytes(msgBody.Length);


            //复制字节到指定数组
            Array.Copy(idbytes, msgByte, 4);
            //从指定数组指定位置,复制到另一数组指定位置,指定长度
            Array.Copy(lenbytes, 0, msgByte, 4, lenbytes.Length);
            Array.Copy(msgBody, 0, msgByte, 8, msgBody.Length);

            //发送
            socket.Send(msgByte);

            //清空输入框 
            inputMsg.text = "";
        });


        //创建Socket对象
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //连接服务器
        socket.Connect("172.18.32.106", 9999);

        if (socket.Connected)
        {
            print("连接服务器成功!");

            //创建线程,用于处理消息接收
            thread = new Thread(ReceiveData);

            //设置为后台线程
            thread.IsBackground = true;
            //启动
            thread.Start();
        }
        else
        {
            print("连接失败!");
        }
    }

    private void ReceiveData()
    {
        while (true)
        {
            //接收数据,将收到的数据存储在buffers里,数据的长度为len
            int len = socket.Receive(buffers);

            if (len > 8)
            {
                //解析标识
                byte[] idbytes = new byte[4];
                Array.Copy(buffers, 0, idbytes, 0, 4);
                //还原消息标识
                int msgId = BitConverter.ToInt32(idbytes, 0);


                //消息长度
                byte[] lenbytes = new byte[4];
                Array.Copy(buffers, 4, lenbytes, 0, 4);
                //还原消息长度
                int msgLen = BitConverter.ToInt32(lenbytes, 0);


                //消息主体
                byte[] bodybytes = new byte[msgLen];
                Array.Copy(buffers, 8, bodybytes, 0, msgLen);
                //将消息主体还原成字符串
                string msgBody = Encoding.UTF8.GetString(bodybytes);

                //将消息存储为结构体,包括 id,msgbody
                MsgData md = new MsgData();
                md.id = msgId;
                md.msg = msgBody;

                //把收到的消息对象,存储到队列 
                msgQueue.Enqueue(md);
             }
            
        }
    }

    // Update is called once per frame  
    void Update()
    {
        while (msgQueue.Count > 0)
        {
            //从头取出消息结构体
            MsgData data = msgQueue.Dequeue();
            switch (data.id)
            {
                case 1:  //公聊消息
                    txtMsg.AddMsg(data.msg);
                    break;
                case 2://系统消息
                    txtMsg.AddMsg("<color=#ff0000>" + data.msg + "</color>");
                    break;
            }
            
        }
    }

    private void OnDestroy()
    {
        //关闭连接
        socket.Close();
        //停止线程
        thread.Abort();

    }   
} 

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Text;

public class Msg : MonoBehaviour {

    private Text txt;

    private StringBuilder sb = new StringBuilder();
    
    void Start () {
        txt = this.transform.Find("Text").GetComponent<Text>();
    }  
     
    /// <summary>
    /// 向文本框中添加内容 
    /// </summary>
    /// <param name="msg"></param>
    public void AddMsg(string msg)
    {
        //累计消息
        sb.Append(msg + "\n");
        //文本显示内容
        txt.text = sb.ToString();
    }   
} 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值