游戏蛮牛学习群(纯技术交流,不闲聊):539178957
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2236

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 309|回复: 4

[薛飞] Unity极简网络游戏之客户端Socket连接

[复制链接]  [移动端链接]
排名
731
昨日变化
3

16

主题

173

帖子

2802

积分

Rank: 9Rank: 9Rank: 9

UID
686
好友
12
蛮牛币
3627
威望
0
注册时间
2013-7-4
在线时间
1085 小时
最后登录
2018-6-24

专栏作家社区QQ达人

QQ
发表于 2018-6-1 16:45:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
打算在制作一款极简网络游戏(2D)的过程中,做一下记录。极简网络游戏,额,前端Unity、C#,后端也是C#(就会这么点)、SupserSocket,协议用Protobuf,数据库MySql,功能或许会少的可怜……
读了不少大神的文章如http://www.manew.com/forum-47-260-1.html,但没大神会的多,所以一切从简,做一些学习验证
结构也极其简单   客户端——服务器

客户端Socket连接的代码
[C#] 纯文本查看 复制代码
//using Message;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Timers;
using UnityEngine;

namespace TFrame
{
    /// <summary>
    /// 网络管理
    /// </summary>
    public class NetMgr : MonoBehaviour
    {
        public static NetMgr Instance;
        private Socket socket;
        private byte[] buffer;
        private int size = 1024;
        private int protoId;
        private bool isReceiving = false;
        private List<byte> receiveCache = new List<byte>();
        private bool isSending = false;
        private Queue<byte[]> sendCache = new Queue<byte[]>();

        public delegate void Delegate(bool result);
        public Delegate connectCallBack;

        //private string ip = "211.159.159.200";
        private string ip = "127.0.0.1";
        private int port = 6650;

        /// <summary>
        /// 心跳频率 6000毫秒1次
        /// </summary>
        private static float hbRate = 6000;

        private long sendTime = 0;
        private long receiveTime = 0;

        /// <summary>
        /// 定时器
        /// </summary>
        Timer timer = new Timer(hbRate);

        public enum Status
        {
            None,
            Connected,
        };
        public Status status = Status.None;

        public NetMgr()
        {
            timer.Elapsed += new ElapsedEventHandler(HandleMainTimer);
            timer.AutoReset = false;
            timer.Enabled = true;

            buffer = new byte[size];
            receiveCache = new List<byte>();
            sendCache = new Queue<byte[]>();
            Instance = this;
            
            //注册消息
            //MsgMgr.Instance.AddListener(typeof(SToCHeatBeat), OnHeratBeat);
        }

        public void Connect()
        {
            try
            {
                //socket
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

                //Connect
                socket.Connect(IPAddress.Parse(ip), port);
                //BeginReceive
                socket.BeginReceive(buffer, 0, buffer.Length,
                                    SocketFlags.None, EndReceive, buffer);
                socket.SendTimeout = 3;
                Debug.Log("连接成功");

                //状态
                status = Status.Connected;
                connectCallBack(true);

            }
            catch (Exception e)
            {
                Debug.Log("连接失败:" + e.Message);
                connectCallBack(false);
            }
        }

        /// <summary>
        /// 接收回调
        /// </summary>
        /// <param name="ar"></param>
        private void EndReceive(IAsyncResult ar)
        {
            try
            {
                if (socket == null)
                {
                    return;
                }
                if (!socket.Connected)
                {
                    return;
                }
                int count = socket.EndReceive(ar);
                if (count > 0)
                {
                    byte[] data = new byte[count];
                    Buffer.BlockCopy(buffer, 0, data, 0, count);
                    OnReceive(data);

                    socket.BeginReceive(buffer, 0,
                             buffer.Length, SocketFlags.None,
                             EndReceive, buffer);
                }
                else
                {
                    //包尺寸有问题,断线处理
                    Debug.Log("包尺寸有问题,断线处理");
                    status = Status.None;
                    connectCallBack(false);
                    Close();
                }

            }
            catch (Exception e)
            {
                Debug.Log("ReceiveCb失败:" + e.Message);
                status = Status.None;
                connectCallBack(false);
                Close();
            }
        }

        /// <summary>
        /// 消息处理
        /// </summary>
        /// <param name="data"></param>
        private void OnReceive(byte[] data)
        {
            //将接收到的数据放入数据池中
            receiveCache.AddRange(data);
            //如果没在读数据
            if (!isReceiving)
            {
                isReceiving = true;
                ReadData();
            }
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        private void ReadData()
        {
            byte[] data = NetCode.Decode(ref protoId, ref receiveCache);

            if (data != null)
            {
                //收到的数据放到消息队列
                //Type protoType = ProtoDic.GetProtoTypeByProtoId(protoId);
                //object tos = ProtoBuf.Serializer.Deserialize(protoType, new MemoryStream(data));
                //MsgMgr.Instance.eventDict.Enqueue(new KeyValuePair<Type, object>(protoType, tos));
                //尾递归,继续读取数据
                ReadData();
            }
            else
            {
                isReceiving = false;
            }
        }

        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="obj"></param>
        public void Send(object obj)
        {
            if (status != Status.Connected)
            {
                Debug.LogError("[Connection]还没链接就发送数据是不好的");
                return;
            }
            //序列化消息存入发送队列中
            //if (!ProtoDic.ContainProtoType(obj.GetType()))
            //{
            //    Debug.LogError("未知协议号");
            //    return;
            //}

            //byte[] data = NetCode.Encode(obj);
            //sendCache.Enqueue(data);
            Send();
        }

        byte[] sendData;
        /// <summary>
        /// 发送
        /// </summary>
        private void Send()
        {
            if (socket == null)
            {
                return;
            }

            if (!socket.Connected)
            {
                return;
            }

            try
            {
                if (sendCache.Count == 0)
                {
                    isSending = false;
                    return;
                }
                isSending = true;
                sendData = sendCache.Dequeue();
                //Debug.Log("data.Length:" + data.Length); 
                socket.BeginSend(sendData, 0, sendData.Length, SocketFlags.None, null, null);
                isSending = false;
                Send();
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
            }
        }

        private void FixedUpdate()
        {


        }

        private void HandleMainTimer(object sender, ElapsedEventArgs e)
        {
            HeartBeat();
            timer.Start();
        }

        void HeartBeat()
        {
            //心跳
            if (status == Status.Connected)
            {
                //CToSHeatBeat hb = new CToSHeatBeat();
                //TimeSpan ts = new TimeSpan(DateTime.Now.Ticks);
                //hb.time = (long)ts.TotalMilliseconds;
                //sendTime = hb.time;
                //Send(hb);
            }
            //断线重连
        }

        void OnHeratBeat(object protocol)
        {
            //SToCHeatBeat sthb = protocol as SToCHeatBeat;
            //TimeSpan ts = new TimeSpan(DateTime.Now.Ticks);
            //receiveTime = (long)ts.TotalMilliseconds;
            //Debug.LogWarning("正确的延迟:" + (receiveTime - sendTime) / 2);
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <returns></returns>
        public void Close()
        {
            if (socket != null)
            {
                try
                {
                    if (socket.Connected)
                    {
                        socket.Shutdown(SocketShutdown.Both);
                        socket.Disconnect(true);
                        socket.Close();
                    }

                    Debug.Log("关闭socket");
                }
                catch (Exception e)
                {
                    Debug.Log("关闭失败:" + e.Message);
                }
                socket = null;

                status = Status.None;
            }
        }
          
        //描述
        public string GetDesc(byte[] bytes)
        {
            string str = "";
            if (bytes == null) return str;
            for (int i = 0; i < bytes.Length; i++)
            {
                int b = (int)bytes[i];
                str += b.ToString() + " ";
            }
            return str;
        }

        private void OnApplicationPause(bool pause)
        {
            Close();
        }

        private void OnApplicationFocus(bool focus)
        {
            //重新登录
        }

        /// <summary>
        /// 当应用程序退出或编辑器结束运行
        /// </summary>
        private void OnApplicationQuit()
        {
            Debug.Log("Close");
            Close();
            timer.Stop();
        }
    }
}



接下来是服务器端SuperSocket相关的内容,下一篇讲



回复

使用道具 举报

4四处流浪
308/500
排名
13559
昨日变化
2

2

主题

189

帖子

308

积分

Rank: 4

UID
282383
好友
0
蛮牛币
240
威望
0
注册时间
2018-5-23
在线时间
63 小时
最后登录
2018-6-22
发表于 2018-6-2 20:55:01 | 显示全部楼层
okk !!!!!!!!!!!!!!!!
[发帖际遇]: Helle2018 乐于助人,奖励 2 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

4四处流浪
375/500
排名
5566
昨日变化
3

3

主题

45

帖子

375

积分

Rank: 4

UID
259967
好友
0
蛮牛币
295
威望
0
注册时间
2017-12-16
在线时间
105 小时
最后登录
2018-6-21
发表于 2018-6-4 10:56:14 | 显示全部楼层
火钳刘明!!!!!!!!!!!!!!!!!

回复

使用道具 举报

5熟悉之中
528/1000
排名
6055
昨日变化

4

主题

155

帖子

528

积分

Rank: 5Rank: 5

UID
234410
好友
2
蛮牛币
749
威望
0
注册时间
2017-7-26
在线时间
167 小时
最后登录
2018-6-22
发表于 2018-6-4 11:52:41 | 显示全部楼层
火钳刘明!!!!!!!!!!!!!!!!!
别忘了粘包问题

回复 支持 反对

使用道具 举报

排名
731
昨日变化
3

16

主题

173

帖子

2802

积分

Rank: 9Rank: 9Rank: 9

UID
686
好友
12
蛮牛币
3627
威望
0
注册时间
2013-7-4
在线时间
1085 小时
最后登录
2018-6-24

专栏作家社区QQ达人

QQ
 楼主| 发表于 2018-6-4 20:10:56 | 显示全部楼层
随幻Kaller 发表于 2018-6-4 11:52
火钳刘明!!!!!!!!!!!!!!!!!
别忘了粘包问题


http://www.manew.com/thread-134935-1-1.html

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表