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