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 + " "; 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; } } } }