using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading; namespace danmu
{
class Program
{
private static string SERVER_DOMAIN = "openbarrage.douyutv.com";
private static int SERVER_PORT = 8601;
private static int ROOM_ID = 288016;
private static string FIX_TAIL = String.Empty; //拼接处理后被丢弃的数据,防止弹幕丢失
class BrrageMsg
{
public string Name = String.Empty;
public string Txt = String.Empty;
}
static void Main(string[] args)
{
try
{
Socket tcpClient = InitTcp(SERVER_DOMAIN, SERVER_PORT);
Thread getDanmuThread = new Thread(GetDanmu);
getDanmuThread.Start(tcpClient);
Thread keepAliveThread = new Thread(KeepAlive);
keepAliveThread.Start(tcpClient);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
} static Socket InitTcp(string host, int port)
{
IPHostEntry hostInfo = Dns.GetHostEntry(host);
IPAddress ipAddress = hostInfo.AddressList[0]; //域名转IP
IPEndPoint ipe = new IPEndPoint(ipAddress, port);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(ipe);
return s;
}
static byte[] DataToBytes(string data)
{
string dantaNew = data + "\0";
byte[] bodyDataByte = Encoding.UTF8.GetBytes(dantaNew);
byte[] cType = BitConverter.GetBytes(689); int dataLength = dantaNew.Length + cType.Length + 8;
byte[] dataLengthByte = BitConverter.GetBytes(dataLength);
byte[] dataLengthByte2 = BitConverter.GetBytes(dataLength);
byte[] result = new byte[dataLength + 4]; Array.Copy(dataLengthByte, 0, result, 0, 4);
Array.Copy(dataLengthByte2, 0, result, 4, 4);
Array.Copy(cType, 0, result, 8, 4);
Array.Copy(bodyDataByte, 0, result, 12, bodyDataByte.Length);
byte[] source = new byte[result.Length];
Array.Copy(result, 0, source, 0, result.Length);
return result;
} static void GetDanmu(object obj)
{
Socket tcpClient = (Socket)obj;
string login = "type@=loginreq/roomid@=" + ROOM_ID + "/";
byte[] loginBytes = DataToBytes(login);
tcpClient.Send(loginBytes);
string joingroup = "type@=joingroup/rid@=" + ROOM_ID + "/gid@=-9999/";
byte[] joingroupBytes = DataToBytes(joingroup);
tcpClient.Send(joingroupBytes);
string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
while (true)
{
bytes = tcpClient.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
recvStr = Encoding.UTF8.GetString(recvBytes, 0, bytes);
ShowMsg(recvStr);
}
} static BrrageMsg GetMsgType(string[] msgType)
{
BrrageMsg brrageMsg = new BrrageMsg();
foreach (string keyValueTemp in msgType)
{
string[] keyValue = Regex.Split(keyValueTemp, "@=", RegexOptions.IgnoreCase);
if (keyValue.Length >= 2)
{
string key = keyValue[0];
string[] textArr = new string[keyValue.Length - 1];
Array.Copy(keyValue, 1, textArr, 0, keyValue.Length - 1);
string value = String.Join("@", textArr);
if (key == "nn")
{
brrageMsg.Name = value;
}
if ((key == "txt"))
{
brrageMsg.Txt = value;
}
}
}
return brrageMsg;
}
static void ShowMsg(string msg)
{
msg = FIX_TAIL + msg;
string[] chatmsgArray = Regex.Split(msg, "type@=", RegexOptions.IgnoreCase);
FIX_TAIL = chatmsgArray[chatmsgArray.Length - 1]; //截取最后的丢弃数据,放在下个包的开头,防止数据丢失
string[] newChatmsgArrayArr = new string[chatmsgArray.Length - 1];
Array.Copy(chatmsgArray, 0, newChatmsgArrayArr, 0, chatmsgArray.Length - 1); foreach (string t in newChatmsgArrayArr)
{
string[] msgType = t.Split('/');
if (msgType.Length >= 2)
{
string type = msgType[0];
if (type == "chatmsg")
{
BrrageMsg brrageMsg = GetMsgType(msgType);
string result = String.Format("[{0}]: {1}", brrageMsg.Name, brrageMsg.Txt);
Console.WriteLine(result +" "+ DateTime.Now );
}
}
}
}
static void KeepAlive(object obj)
{
Socket tcpClient = (Socket)obj;
byte[] aliveMsg = DataToBytes("type@=mrkl/");
while (true)
{
tcpClient.Send(aliveMsg);
Thread.Sleep(40000);
}
}
}
}

  

2: another - (not test)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace C1
{
class Program
{
public static string RoomID;
static void Main(string[] args)
{
Console.Title = "斗鱼弹幕小助手";
Console.ForegroundColor = ConsoleColor.Gray;
// 设定服务器IP地址
IPAddress ip = IPAddress.Parse("115.231.96.19");
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clientSocket.Connect(new IPEndPoint(ip, 12604)); //配置服务器IP与端口
Console.WriteLine("连接服务器成功");
Console.WriteLine("请输入房间ID号");
RoomID = Console.ReadLine(); string send = "type@=loginreq/username@=visitor1687994/password@=1234567890123456/roomid@=" + RoomID + "/dfl@=sn@AA=105@ASss@AA=1/ct@=0/ver@=20180413/aver@=2018051611/";
MsgBody sBody = new MsgBody(send);
clientSocket.Send(sBody.ToByteArray());
Console.WriteLine("向服务器发送消息:{0}" + send);
}
catch (Exception e)
{
Console.WriteLine("连接服务器失败,请按回车键退出!");
return;
}
//通过clientSocket接收数据 Thread receiveThread = new Thread(reMsg);
receiveThread.Start(clientSocket);
Thread receiveThread2 = new Thread(SendMsg);
receiveThread2.Start(clientSocket);
Console.ReadLine();
}
/// <summary>
/// 取中间值
/// </summary>
/// <param name="allStr"></param>
/// <param name="firstStr"></param>
/// <param name="lastStr"></param>
/// <returns></returns>
public static string GetStringMid(string allStr, string firstStr, string lastStr)
{
try
{
int index1 = allStr.IndexOf(firstStr);
int index2 = allStr.IndexOf(lastStr, index1 + firstStr.Length); if (index1 < 0 || index2 < 0)
{
return "";
} index1 = index1 + firstStr.Length;
index2 = index2 - index1; if (index1 < 0 || index2 < 0)
{
return "";
}
return allStr.Substring(index1, index2);
}
catch (Exception ex)
{ throw;
}
} static void reMsg(object socket)
{
byte[] saveArr = new byte[0];
byte[] result = new byte[1024];
while (true)
{
try
{
int receiveLength = ((Socket)socket).Receive(result);
if (receiveLength > 0)
{
if (saveArr.Length > 0)
{
byte[] arr = new byte[saveArr.Length + receiveLength];
Array.Copy(saveArr, 0, arr, 0, saveArr.Length);
Array.Copy(result, 0, arr, saveArr.Length, receiveLength);
result = arr;
receiveLength = result.Length;
}
int head = 0;
if (result.Length < 4)
{
saveArr = new byte[receiveLength];
Array.Copy(result, 0, saveArr, 0, saveArr.Length);
continue;
}
head = BitConverter.ToInt32(SubByte(result, 0, 4), 0); string str = string.Empty;
if (head > (receiveLength - 4))
{
saveArr = new byte[result.Length];
Array.Copy(result, 0, saveArr, 0, saveArr.Length);
continue;
}
int index = 0;
do
{
MsgBody reBodyMsg = new MsgBody(result.Take(head + 4).ToArray());
str = reBodyMsg.BodyData;
index = head + 4;
if (str.IndexOf("keeplive") != -1)
{
//心跳
}
else if (str.IndexOf("type@=chatmsg") != -1)
{
string txt = GetStringMid(str, "txt@=", "/");
string name = "[" + GetStringMid(str, "nn@=", "/") + "]"; //name = name.PadRight(15);
name = name + new string(' ', 30 - Encoding.Default.GetByteCount(name));
name = string.Format("{0}发送弹幕", name);
name = name + new string(' ', 50 - Encoding.Default.GetByteCount(name));
Console.WriteLine(name + txt); }
else if (str.IndexOf("type@=uenter") != -1)
{
str = "欢迎[" + GetStringMid(str, "nn@=", "/") + "]"; str = str + new string(' ', 30 - Encoding.Default.GetByteCount(str)); Console.WriteLine("{0}进入直播间", str);
}
else if (str.IndexOf("loginres") != -1)
{
string send = "type@=joingroup/rid@=" + RoomID + "/gid@=-9999/";
MsgBody sBody = new MsgBody(send);
((Socket)socket).Send(sBody.ToByteArray());
}
else
{
// Console.WriteLine("接收服务器消息:{0}", str);
}
if (index < receiveLength)
{
try
{
result = SubByte(result, index, receiveLength - index);
if (result.Length <= 12)
{
saveArr = new byte[result.Length];
Array.Copy(result, 0, saveArr, 0, saveArr.Length);
break;
}
head = BitConverter.ToInt32(SubByte(result, 0, 4), 0);
if (result.Length < (head + 4))
{
saveArr = new byte[result.Length];
Array.Copy(result, 0, saveArr, 0, saveArr.Length);
break;
}
receiveLength = result.Length;
continue;
}
catch (Exception ex)
{ throw;
}
}
saveArr = new byte[0];
break;
} while (true); } }
catch (Exception ex)
{ throw;
}
}
} /// <summary>
/// 心跳
/// </summary>
/// <param name="socket"></param>
static void SendMsg(object socket)
{
Socket sk = (Socket)socket;
while (true)
{
//
byte[] b = new byte[] { 0x54, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xB1, 0x02, 0x00, 0x00 };
List<byte> sendData = new List<byte>(b);
sendData.AddRange(Encoding.UTF8.GetBytes("type@=keeplive/tick@=" + GetCurrentTimeUnix() + "/vbw@=0/k@=23d36a0db24136aabee566e0aa748344/"));
sendData.Add(0x00);
sk.Send(sendData.ToArray());
Thread.Sleep(15000);
}
} /// <summary>
/// 获取当前本地时间戳
/// </summary>
/// <returns></returns>
public static long GetCurrentTimeUnix()
{
TimeSpan cha = (DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)));
long t = (long)cha.TotalSeconds;
return t;
}
/// <summary>
/// 字符串MD5
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string md5(string input)
{
//chenwancheng0true1
byte[] buffer = MD5.Create().ComputeHash(Encoding.GetEncoding("ISO-8859-1").GetBytes(input));
return binl2hex(buffer);
} public static string binl2hex(byte[] buffer)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < buffer.Length; i++)
{
builder.Append(buffer[i].ToString("x2"));
}
return builder.ToString().ToLower();
}
/// <summary>
/// 截取字节数组
/// </summary>
/// <param name="srcBytes">要截取的字节数组</param>
/// <param name="startIndex">开始截取位置的索引</param>
/// <param name="length">要截取的字节长度</param>
/// <returns>截取后的字节数组</returns>
public static byte[] SubByte(byte[] srcBytes, int startIndex, int length)
{
System.IO.MemoryStream bufferStream = new System.IO.MemoryStream();
byte[] returnByte = new byte[] { };
if (srcBytes == null) { return returnByte; }
if (startIndex < 0) { startIndex = 0; }
if (startIndex < srcBytes.Length)
{
if (length < 1 || length > srcBytes.Length - startIndex) { length = srcBytes.Length - startIndex; }
bufferStream.Write(srcBytes, startIndex, length);
returnByte = bufferStream.ToArray();
bufferStream.SetLength(0);
bufferStream.Position = 0;
}
bufferStream.Close();
bufferStream.Dispose();
return returnByte;
} }
} using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace C1
{
public class MsgBody
{
public MsgBody()
{ }
public MsgBody(string str)
{
this.BodyData = str;
ToByteArray();
}
public MsgBody(byte[] b)
{
this.Source = b;
SetValues();
}
public int DataLength;
public byte[] DataLength_Byte; public int DataLength_2;
public byte[] DataLength_2_Byte; public int Cmd = 689;
public byte[] Cmd_Byte; public string BodyData;
public byte[] BodyData_Byte; public byte End = 0; public byte[] Source; public byte[] ToByteArray()
{
BodyData_Byte = Encoding.UTF8.GetBytes(BodyData);
Cmd_Byte = BitConverter.GetBytes(Cmd);
DataLength = DataLength_2 = BodyData_Byte.Length + Cmd_Byte.Length + 4 + 1;
DataLength_Byte = BitConverter.GetBytes(DataLength);
DataLength_2_Byte = BitConverter.GetBytes(DataLength_2); byte[] result = new byte[DataLength + 4];
Array.Copy(DataLength_Byte, 0, result, 0, 4);
Array.Copy(DataLength_2_Byte, 0, result, 4, 4);
Array.Copy(Cmd_Byte, 0, result, 8, 4);
Array.Copy(BodyData_Byte, 0, result, 12, BodyData_Byte.Length);
Source = new byte[result.Length];
Array.Copy(result, 0, Source, 0, result.Length);
return result;
} public void SetValues()
{
try
{
DataLength_Byte = Program.SubByte(Source, 0, 4);
DataLength_2_Byte = Program.SubByte(Source, 4, 4);
Cmd_Byte = Program.SubByte(Source, 8, 4);
BodyData_Byte = Program.SubByte(Source, 12, Source.Length - 13);
End = Program.SubByte(Source, Source.Length - 2, 1)[0]; DataLength = BitConverter.ToInt32(DataLength_Byte, 0);
DataLength_2 = BitConverter.ToInt32(DataLength_2_Byte, 0);
Cmd = BitConverter.ToInt32(Cmd_Byte, 0);
BodyData = Encoding.UTF8.GetString(BodyData_Byte);
}
catch (Exception ex)
{ throw;
}
}
}
}

  

最新文章

  1. PTS PCR DTS 详解
  2. Java开发之单例设计模式
  3. SpringInAction读书笔记--第1章Spring之旅
  4. JS字符串常用方法
  5. IMAGE_SECTION_HEADER
  6. HDU 4544 湫湫系列故事――消灭兔子
  7. EasyUI - Tree 树组件
  8. NLP+VS︱深度学习数据集标注工具、方法摘录,欢迎补充~~
  9. 【Linux】-NO.160.Linux.1 -【升级Centos7】
  10. 【CSS3】响应式布局
  11. hdu5371 manacher + 线段树
  12. 解压.bz2失败
  13. centos安装lamp
  14. python数字前自动补零
  15. 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树
  16. 基于RDBMS的OLAP的解决方案
  17. [Selenium]验证点了某个Button之后无反应
  18. Scrum项目6.0 和8910章读后感
  19. 有关一道printf 的面试题
  20. 贪心+离散化+线段树上二分。。。 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest G. Of Zorcs and Axes

热门文章

  1. php-fpm内存泄漏问题排查
  2. linux下mysql的常用命令
  3. zabbix布置mysql主从监控
  4. python之堆排序算法代码
  5. SpringBoot页面展示Thymeleaf
  6. 三、Ubuntu16.04 安装Jira8.2.2(自带中文包)和破解
  7. kettle批量导入json数据
  8. vim替换
  9. java 死锁演示
  10. Excel筛选操作