public RtmpServer( SerializationContext context, X509Certificate2 cert = null, ObjectEncoding object_encoding = ObjectEncoding.Amf0, ParameterAuthCallback publishParameterAuth = null, ParameterAuthCallback playParameterAuth = null, string bindIp = "0.0.0.0", int bindRtmpPort = 1935, int bindWebsocketPort = -1 ) { this.context = context; objectEncoding = object_encoding; if (bindWebsocketPort != -1) { var server = new WebSocketServer("ws://" + bindIp.ToString() + ":" + bindWebsocketPort.ToString()); if (cert != null) { this.cert = cert; server.Certificate = cert; server.EnabledSslProtocols = SslProtocols.Default; } server.ListenerSocket.NoDelay = true; server.Start(socket => { socket.OnOpen = () => { var path = socket.ConnectionInfo.Path.Split('/'); if (path.Length != 3) { socket.Close(); } ushort client_id = GetNewClientId(); IStreamConnect connect = new WebsocketConnect(socket, context, object_encoding); lock (connects) { connects.Add(client_id, new StreamConnectState() { Connect = connect, LastPing = DateTime.UtcNow, ReaderTask = null, WriterTask = null }); } try { SendMetadata(path[1], path[2], connect, flvHeader: true); ConnectToClient(path[1], path[2], client_id, ChannelType.Audio); ConnectToClient(path[1], path[2], client_id, ChannelType.Video); } catch { Close(client_id); } }; socket.OnPing = b => socket.SendPong(b); }); } if (publishParameterAuth != null) { this.publishParameterAuth = publishParameterAuth; } if (playParameterAuth != null) { this.playParameterAuth = playParameterAuth; } ioThread = new Thread(() => { while (true) { foreach (var current in connects) { StreamConnectState state = current.Value; ushort client_id = current.Key; IStreamConnect connect = state.Connect; if (connect.IsDisconnected) { Close(client_id); continue; } try { if (state.WriterTask == null || state.WriterTask.IsCompleted) { state.WriterTask = connect.WriteOnceAsync(); } if (state.WriterTask.IsCanceled || state.WriterTask.IsFaulted) { throw state.WriterTask.Exception; } if (state.LastPing == null || DateTime.UtcNow - state.LastPing >= new TimeSpan(0, 0, PingPeriod)) { connect.PingAsync(PingTimeout); state.LastPing = DateTime.UtcNow; } if (state.ReaderTask == null || state.ReaderTask.IsCompleted) { state.ReaderTask = connect.ReadOnceAsync(); } if (state.ReaderTask.IsCanceled || state.ReaderTask.IsFaulted) { throw state.ReaderTask.Exception; } } catch { Close(client_id); continue; } } var prepare_add_length = prepare_to_add.Count; if (prepare_add_length != 0) { for (int i = 0; i < prepare_add_length; i++) { var current = prepare_to_add[0]; connects.Add(current.Key, current.Value); prepare_to_add.RemoveAt(0); } } var prepare_remove_length = prepare_to_remove.Count; if (prepare_remove_length != 0) { for (int i = 0; i < prepare_remove_length; i++) { var current = prepare_to_remove[0]; connects.Remove(current); prepare_to_remove.RemoveAt(0); } } } }) { IsBackground = true }; ioThread.Start(); listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.NoDelay = true; IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(bindIp), bindRtmpPort); listener.Bind(localEndPoint); listener.Listen(10); }
/// <summary> /// 启动连接状态检查线程 /// 执行rtmp的读写异步任务 /// </summary> void ClientWorkHandler() { _clientWorkThread = new Thread(() => { while (true) { try { if (ClientSessions.Count() < 1) { Thread.Sleep(1); continue; } ClientSessionDictionary nclientSessions = null; lock (_locker) { nclientSessions = ClientSessions.Clone() as ClientSessionDictionary; } Parallel.ForEach(nclientSessions, current => { ClientSession state = current.Value; ushort client_id = current.Key; IStreamConnect connect = state.Connect; try { if (connect.IsDisconnected) { DisconnectSession(client_id); } else { if (state.WriterTask == null) { state.WriterTask = connect.WriteOnceAsync(); } else { if (state.WriterTask.IsCompleted) { state.WriterTask = connect.WriteOnceAsync(); } if (state.WriterTask.IsCanceled || state.WriterTask.IsFaulted) { this.DisconnectSession(current.Key); //throw state.WriterTask.Exception; } if (state.LastPing == null || DateTime.UtcNow - state.LastPing >= new TimeSpan(0, 0, _pingPeriod)) { connect.PingAsync(_pingTimeout); state.LastPing = DateTime.UtcNow; } if (state.ReaderTask == null || state.ReaderTask.IsCompleted) { state.ReaderTask = connect.ReadOnceAsync(); } if (state.ReaderTask.IsCanceled || state.ReaderTask.IsFaulted) { this.DisconnectSession(current.Key); //throw state.ReaderTask.Exception; } } } } catch { DisconnectSession(client_id); } }); } catch (Exception ex) { FleckLog.Error("ConnectStateCheckUp.Thread.Error", ex); } } }) { IsBackground = true }; _clientWorkThread.Start(); }