zoukankan      html  css  js  c++  java
  • socket 客户端

    socket 客户端 的一些想法

    -----------------包头--------------------------

    4byte  4byte  2byte  2byte

    数据长  数据长   约定数字  0

    ------------------------------------------------

    1.登录

    2.每隔15秒发送心跳包

    3.死循环接收数据,把收到的byte[]塞到List<byte>(队列,先进先出)(生产者)

    4.List<byte> 要有同步锁

    5.死循环读取List<byte>,把数据解析出来(消费者)(可以多消费者)

    ----------------------------------2017/3/22 更新------------------------------------------------------

    感觉好慢,不能即时展现数据

    1.心跳包

     1         #region 服务器心跳连接
     2 
     3         private static readonly System.DateTime Jan1st1970 = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
     4 
     5         /// <summary>
     6         /// 服务器心跳连接
     7         /// </summary>
     8         public void keepAlive()
     9         {
    10             while (readyFlag)
    11             {
    12                 //获取与弹幕服务器保持心跳的请求数据包 按照需求生成心跳包并转成byte[]
    13                 byte[] keepAliveRequest = DyMessage.getKeepAliveData((int)(((long)(System.DateTime.UtcNow - Jan1st1970).TotalMilliseconds) / 1000));
    14 
    15                 try
    16                 {
    17                     //向弹幕服务器发送心跳请求数据包
    18                     bos.Write(keepAliveRequest, 0, keepAliveRequest.Length);
    19                     bos.Flush();
    20                     //sendToText("exMsg","发送心跳包成功!");
    21 
    22                     //设置间隔45秒再发送心跳协议
    23                     Thread.Sleep(45000);        //keep live at least once per minute
    24 
    25                 }
    26                 catch (Exception e)
    27                 {
    28                     //e.printStackTrace();
    29                     sendToText("exMsg", "错误:发送心跳包失败!");
    30                     readyFlag = false;
    31                 }
    32             }
    33         }
    34         #endregion

    2.接受数据

      1         #region 新获取弹幕
      2 
      3         //缓存池
      4         private List<byte> list = new List<byte>();
      5         //同步锁
      6         private object myLock = new object();
      7         private Semaphore TaskSemaphore = new Semaphore(0, 256);
      8 
      9      //解析数据
     10         public void KeepRead(object data)
     11         {
     12             //int Index = (int)data;
     13 
     14             while (readyFlag)//死循环
     15             {
     16                 TaskSemaphore.WaitOne();//等待
     17                 string dataStr = "";
     18                 lock (myLock)//同步锁
     19                 {
     20                     if (list.Count > 12)//12个长度的包头
     21                     {
     22                         byte[] topBytes = list.Take(12).ToArray();//拿出包头
     23 
     24                         byte[] packSizeBuffer1 = new byte[4];//4 字节小端整数,表示整条消息(包括自身)长度(字节数)。
     25                         Array.Copy(topBytes, 0, packSizeBuffer1, 0, 4);//消息长度 
     26                         int packSize1 = BitConverter.ToInt32(packSizeBuffer1, 0);//转成长度
     27 
     28                         byte[] packSizeBuffer2 = new byte[4];//4 字节小端整数,表示整条消息(包括自身)长度(字节数)。
     29                         Array.Copy(topBytes, 4, packSizeBuffer2, 0, 4);//消息长度 
     30                         int packSize2 = BitConverter.ToInt32(packSizeBuffer2, 0);//转成长度
     31 
     32                         byte[] packTypeBuffer = new byte[4];//4 字节小端整数,表示整条消息(包括自身)长度(字节数)。
     33                         Array.Copy(topBytes, 8, packTypeBuffer, 0, 2);//消息长度 
     34                         int packType = BitConverter.ToInt32(packTypeBuffer, 0);//转成长度
     35 
     36                         if (packSize1 == packSize2 && packType == DY_MESSAGE_TYPE_SERVER)//根据需求验证包头
     37                         {
     38                             int packSize = packSize1 + 4;//一个包长度 = 包头长+数据长
     39 
     40                             if (list.Count >= packSize)//如果缓存数据够一个包的长度
     41                             {
     42                                 byte[] totalBytes = list.Take(packSize).ToArray();//拿到一个包的数据
     43                                 //Console.WriteLine("截取数据:" + Newtonsoft.Json.JsonConvert.SerializeObject(totalBytes));
     44 
     45                                 list.RemoveRange(0, packSize);//取出后删除  
     46                                 //Console.WriteLine("截取后源数据:" + Newtonsoft.Json.JsonConvert.SerializeObject(list));
     47 
     48                                 dataStr = Encoding.UTF8.GetString(totalBytes, 12, totalBytes.Length - 12);//包的数据转换成string
     49                                 //Console.WriteLine("截取数据输出:" + dataStr);
     50 
     51                                 //对单一数据包进行解析
     52                                 MsgView msgView1 = new MsgView(dataStr);
     53                                 //分析该包的数据类型,以及根据需要进行业务操作
     54                                 parseServerMsg(msgView1.getMessageList());
     55 
     56                                 //Console.WriteLine(Index + "");
     57                             }
     58                         }
     59                     }
     60                 }
     61             }
     62         }
     63 
     64         public void KeepMsgToList()
     65         {
     66             while (readyFlag)
     67             {
     68                 if (client == null || !client.Connected)//如果tcpclient为null或断开连接
     69                 {
     70                     break;
     71                 }
     72                 else 
     73                 {
     74                     try
     75                     {
     76                         byte[] bytes = new byte[client.ReceiveBufferSize];
     77                         int readSize = m_Reader.Read(bytes, 0, (int)client.ReceiveBufferSize);//读取数据
     78                         if (readSize > 0)//说明是有读到数据的
     79                         {
     80                             byte[] totalBytes = new byte[readSize];//C#神器,byte[]会自动延长
     81                             Array.Copy(bytes, 0, totalBytes, 0, readSize);//消息长度 
     82                             //totalBytes = totalBytes.Concat(bytes).ToArray();//C#神器,byte[]会自动延长
     83                             lock (myLock)//同步锁
     84                             {
     85                                 list.AddRange(totalBytes);//把数据加到List<byte>中 先进先出
     86                             }
     87                             TaskSemaphore.Release(1);   // 每添加一个任务,信号量加1
     88                         }
     89                     }
     90                     catch (Exception e)
     91                     {
     92                         if (client == null || client.Connected == false)
     93                         {
     94                             shutdown();//注销登录,断开连接,readyFlag=false 等操作
     95                             sendToText("exMsg", "尝试重新连接!");
     96                         }
     97                         else
     98                         {
     99                             sendToText("exMsg", "错误:获取弹幕失败!");
    100                         }
    101                     }
    102                 }
    103             }
    104         }
    105 
    106         #endregion

    启动线程

     1             //保持弹幕服务器心跳
     2             //KeepAlive alive = new KeepAlive();
     3             keepAlive = new Thread(new ThreadStart(danmuClient.keepAlive));
     4             keepAlive.IsBackground = true;
     5             keepAlive.Start();
     6             //AddTalkMessage("开始发送心跳包!
    ");
     7 
     8             //获取弹幕服务器发送的所有信息
     9             //KeepGetMsg msg = new KeepGetMsg();
    10             keepGetMsg = new Thread(new ThreadStart(danmuClient.KeepMsgToList));
    11             keepGetMsg.IsBackground = true;
    12             keepGetMsg.Start();
    13             //AddTalkMessage("开始获取弹幕!
    ");
    14 
    15             //解析信息
    16             for (int i = 0; i < 10; i++)  
    17             {  
    18                 Thread keepReadMsg = new Thread(new ParameterizedThreadStart(danmuClient.KeepRead));  
    19                 keepReadMsg.IsBackground = true;
    20                 keepReadMsg.Start(i);
    21             } 

     -----------------------------修改----------------------------------------

     1         public void KeepMsgToString()
     2         {
     3             while (readyFlag)
     4             {
     5                 if (client == null || !client.Connected)
     6                 {
     7                     break;
     8                 }
     9                 else //if (ntwStream.DataAvailable)//说明是有读到数据的
    10                 {
    11                     try
    12                     {
    13                         byte[] bytes = new byte[client.ReceiveBufferSize];
    14                         int readSize = m_Reader.Read(bytes, 0, (int)client.ReceiveBufferSize);
    15                         if (readSize > 0)//说明是有读到数据的
    16                         {
    17                             byte[] totalBytes = new byte[readSize];//C#神器,byte[]会自动延长
    18                             Array.Copy(bytes, 0, totalBytes, 0, readSize);//消息长度 
    19                             list.AddRange(totalBytes);
    20 
    21                             //获取数据完成,开始解析
    22                             
    23                                 string dataStr = "";
    24                                 while (list.Count > 12)
    25                                 {
    26                                     byte[] topBytes = list.Take(12).ToArray();
    27 
    28                                     byte[] packSizeBuffer1 = new byte[4];//4 字节小端整数,表示整条消息(包括自身)长度(字节数)。
    29                                     Array.Copy(topBytes, 0, packSizeBuffer1, 0, 4);//消息长度 
    30                                     int packSize1 = BitConverter.ToInt32(packSizeBuffer1, 0);//转成长度
    31 
    32                                     byte[] packSizeBuffer2 = new byte[4];//4 字节小端整数,表示整条消息(包括自身)长度(字节数)。
    33                                     Array.Copy(topBytes, 4, packSizeBuffer2, 0, 4);//消息长度 
    34                                     int packSize2 = BitConverter.ToInt32(packSizeBuffer2, 0);//转成长度
    35 
    36                                     byte[] packTypeBuffer = new byte[4];//4 字节小端整数,表示整条消息(包括自身)长度(字节数)。
    37                                     Array.Copy(topBytes, 8, packTypeBuffer, 0, 2);//消息长度 
    38                                     int packType = BitConverter.ToInt32(packTypeBuffer, 0);//转成长度
    39 
    40                                     if (packSize1 == packSize2 && packType == DY_MESSAGE_TYPE_SERVER)
    41                                     {
    42                                         int packSize = packSize1 + 4;//一个包长度
    43 
    44                                         if (list.Count >= packSize)
    45                                         {
    46                                             byte[] totalBytes1 = list.Take(packSize).ToArray();
    47                                             //Console.WriteLine("截取数据:" + Newtonsoft.Json.JsonConvert.SerializeObject(totalBytes));
    48 
    49                                             list.RemoveRange(0, packSize);//取出后删除  
    50                                             //Console.WriteLine("截取后源数据:" + Newtonsoft.Json.JsonConvert.SerializeObject(list));
    51 
    52                                             dataStr = Encoding.UTF8.GetString(totalBytes1, 12, totalBytes1.Length - 12);
    53                                             //Console.WriteLine("截取数据输出:" + dataStr);
    54 
    55                                             //对单一数据包进行解析
    56                                             MsgView msgView1 = new MsgView(dataStr);
    57                                             //分析该包的数据类型,以及根据需要进行业务操作
    58                                             parseServerMsg(msgView1.getMessageList());
    59 
    60                                         }
    61                                         else
    62                                         {
    63                                             break;
    64                                         }
    65                                     }
    66                                 }
    67                             
    68                         }
    69                     }
    70                     catch (Exception e)
    71                     {
    72                         if (client == null || client.Connected == false)
    73                         {
    74                             shutdown();
    75                             sendToText("exMsg", "尝试重新连接!");
    76                         }
    77                         else
    78                         {
    79                             sendToText("exMsg", "错误:获取弹幕失败!");
    80                         }
    81                     }
    82                 }
    83             }
    84         }

  • 相关阅读:
    环形链表II 找环入口
    最短无序连续子数组 复制数组排序后与原数组相比
    和为K的子数组 暴力 或 hash+前缀
    在排序数组中查找元素的第一个和最后一个位置 二分法+递归
    NodeJs 批量重命名文件,并保存到指定目录
    NodeJs 批量图片瘦身,重设尺寸和图片质量并保存到指定目录
    NodeJs 获取照片拍摄日期和视频拍摄日期,并按日期目录存档
    Oracle迁移记录
    Oracle数据库迁移前的准备工作(创建用户并且分配权限及表空间)
    Oracle 11g R2性能优化 10046 event【转载】
  • 原文地址:https://www.cnblogs.com/margin-gu/p/6589759.html
Copyright © 2011-2022 走看看