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("开始发送心跳包!\r\n");
 7 
 8             //获取弹幕服务器发送的所有信息
 9             //KeepGetMsg msg = new KeepGetMsg();
10             keepGetMsg = new Thread(new ThreadStart(danmuClient.KeepMsgToList));
11             keepGetMsg.IsBackground = true;
12             keepGetMsg.Start();
13             //AddTalkMessage("开始获取弹幕!\r\n");
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         }

 

posted @ 2017-03-20 16:05  margin_gu  阅读(272)  评论(0编辑  收藏  举报