public async Task ConnectAsync(string url, Option?option = null) { if (option.HasValue) { parser = new DanMuPa(option.Value); } using (tcpClient = new TcpClient()) { // 获得roomid var httpClient = new HttpClient(); var bodyText = await httpClient.GetStringAsync(url); var reg = new Regex(@"var\s+ROOMID\s+=\s+(\w+);"); var match = reg.Match(bodyText); var roomId = match.Groups[1].Value; // 获得tcp服务器地址 var xmlText = await httpClient.GetStringAsync($"http://live.bilibili.com/api/player?id=cid:{roomId}"); var xml = XElement.Parse($"<root>{xmlText}</root>"); var host = xml.Element("dm_server").Value; var port = int.Parse(xml.Element("dm_port").Value); // 链接房间 var data = OpenMsg(roomId); Console.WriteLine($"Connect to Room {roomId} on {host}:{port}"); // 连接服务器 await tcpClient.ConnectAsync(host, port); using (var stream = tcpClient.GetStream()) { await stream.WriteAsync(data, 0, data.Length); heartbeat = Task.Run(async() => { var at = DateTimeOffset.Now.ToUnixTimeSeconds(); Byte[] heartBeat = HeartbeatMsg(); while (true) { if (tcpClient.Connected && stream.CanWrite) { SpinWait.SpinUntil(() => DateTimeOffset.Now.ToUnixTimeSeconds() - at >= 29); await stream.WriteAsync(heartBeat, 0, heartBeat.Length); at = DateTimeOffset.Now.ToUnixTimeSeconds(); Debug.WriteLine("Heartbeat"); } else { Debug.WriteLine("Disconnect"); return; } } }); reciever = Task.Run(async() => { var buffer = new Byte[4]; var at = DateTimeOffset.Now.ToUnixTimeMilliseconds(); while (true) { if (tcpClient.Available > 0 && stream.CanRead) { buffer = new Byte[4]; await stream.ReadAsync(buffer, 0, 4); var MsgLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 0)) - 4; buffer = new Byte[MsgLength]; var recievedByte = 0; while (recievedByte < MsgLength) { recievedByte += await stream.ReadAsync(buffer, recievedByte, MsgLength - recievedByte); } var respText = parser.ParsePackage(buffer); if (!string.IsNullOrWhiteSpace(respText)) { Console.WriteLine(respText); } Debug.WriteLine(BitConverter.ToString(buffer)); } else { SpinWait.SpinUntil(() => DateTimeOffset.Now.ToUnixTimeMilliseconds() - at >= 300); at = DateTimeOffset.Now.ToUnixTimeMilliseconds(); } } }); reciever.Wait(); } } }
public DanMuJi() { parser = new DanMuPa(); }