Red5的一般客户端连接各个事件的触发顺序

本文详细介绍了RED5直播系统中用户登录过程的具体事件流程,包括应用启动、连接、加入房间等关键步骤,并阐述了单个及多个用户进出房间时系统内部事件的触发顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设用户登录的地址是
rtmp://localhost/MyChatRoom/lobby/roomA
以下是事件按先后顺序排列

程序开始
appStart:MyChatRoom
Start:
(在RED5启动的时候会自动去启动APP,从而触发以上事件)

登录
roomStart:/lobby
Start:/lobby
roomStart:/lobby/roomA
Start:/lobby/roomA
appConnect:0
connect
appJoin:0:
roomConnect:0
connect:/lobby
roomJoin:0:/lobby
roomConnect:0
connect:/lobby/roomA
roomJoin:0:/lobby/roomA
第二个用户登录
appConnect:1
connect
appJoin:1:
roomConnect:1
connect:/lobby
roomJoin:1:/lobby
roomConnect:1
connect:/lobby/roomA
roomJoin:1:/lobby/roomA
第二个用户离开
roomDisconnect:1
disconnect:/lobby/roomA
roomLeave:1:/lobby/roomA

roomDisconnect:1
disconnect:/lobby
roomLeave:1:/lobby

appDisconnect:1
disconnect:
appLeave:1:
离开
roomDisconnect:0
disconnect:/lobby/roomA
roomLeave:0:/lobby/roomA

roomStop:/lobby/roomA
stop:/lobby/roomA

roomDisconnect:0
disconnect:/lobby
roomLeave:0:/lobby

roomStop:/lobby
stop:/lobby

appDisconnect
disconnect:
appLeave:0:

总结:
rtmp://localhost/MyChatRoom/lobby/roomA
GlobalScope(default) --> WebScope(MyChatRoom) --> Scope(lobby)
                                                                                                          --> Scope(roomA)
进入时:
先从第一个Scope,lobby开始,
1,执行房间启动ApplicationMBean.roomStart(IScope lobby)
2,执行启动IScopeHandler.start(IScope lobby)
再开始到第二个Scope,roomA开始
3,执行房间启动ApplicationMBean.roomStart(IScope roomA)
4,执行启动IScopeHandler.start(IScope roomA)

5.然后开始执行ApplicationMBean.appConnect(IConnection conn,Object[] params)
6,执行IScopeHandler.connect(IConnection conn, IScope app, Object[] params)
7,然后执行ApplicationMBean.appJoin(IClient client, IScope app)

从第一个Scope,lobby开始,
8,然后执行ApplicationMBean.roomConnect(IConnection conn, Object[] params)
9,执行IScopeHandler.connect(IConnection conn, IScope lobby, Object[] params)
10,执行ApplicationMBean.roomJoin(IClient client, IScope lobby)

第二个Scope,roomA开始,
11,然后执行ApplicationMBean.roomConnect(IConnection conn, Object[] params)
12,执行IScopeHandler.connect(IConnection conn, IScope roomA, Object[] params)
13,执行ApplicationMBean.roomJoin(IClient client, IScope roomA)

当第二个用户进入同一房间时,房间不用重新建立,故从步骤5开始执行

当第二个用户离开时
从最外层的Scope(roomA)开始
1,执行ApplicationMBean.roomDisconnect(IConnection conn)
2,执行IScopeHandler.disconnect(IConnection conn, IScope roomA)
3,执行ApplicationMBean.roomLeave(IClient client, IScope roomA)
再到Scope(lobby)
4,执行ApplicationMBean.roomDisconnect(IConnection conn)
5,执行IScopeHandler.disconnect(IConnection conn, IScope lobby)
6,执行ApplicationMBean.roomLeave(IClient client, IScope lobby)
再是WebScope(MyChatRoom)
7,执行ApplicationMBean.appDisconnect(IConnection conn)
8,执行IScopeHandler.disconnect(IConnection conn, IScope app)
9,执行ApplicationMBean.appLeave(IClient client, IScope app)

当第一个,也是最后一个用户也离开的时候.情况相似.
只不过在roomLeave之后,会接着关闭这个房间
先调用ApplicationMBean.roomStop(IScope room)
再调用IScopeHandler.stop(IScope roomScope)
app不会因为所有客户都不在而自动关闭.

 

帮我检查下代码和修正优化下:TcpCommunication.cs、Form1.cs文件的代码。以下是TcpCommunication.cs的代码using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace _20250721test类 { public class TcpCommunication { // 属性声明(与窗体控件对应) public string IPAddress_str { get; set; } = "127.0.0.1"; public int Port { get; set; } = 8080; public bool IsClientMode { get; set; } = true; public bool IsOpen => _tcpClient?.Connected ?? false; public string ReceivedData { get; private set; } = ""; public string LastError { get; private set; } = ""; // 新增服务器监听状态属性 public bool IsListening { get; private set; } = false; // 核心对象 private TcpListener _tcpServer; private TcpClient _tcpClient; private NetworkStream _stream; private Thread _receiveThread; private bool _isRunning; // 事件定义 public delegate void DataReceivedHandler(string data); public event DataReceivedHandler DataReceived; public delegate void ConnectionStateHandler(bool isConnected); public event ConnectionStateHandler ConnectionStateChanged; public delegate void ErrorHandler(string errorMessage); public event ErrorHandler ErrorOccurred; // 新增服务器监听状态事件 public delegate void ServerListeningHandler(bool isListening); public event ServerListeningHandler ServerListeningChanged; /// <summary> /// 打开TCP连接客户端或服务器) /// </summary> public void Open() { try { if (IsClientMode) { // 客户端模式不变 _tcpClient = new TcpClient(); _tcpClient.Connect(IPAddress.Parse(IPAddress_str), Port); _stream = _tcpClient.GetStream(); _isRunning = true; StartReceiving(); ConnectionStateChanged?.Invoke(true); // 连接成功 } else { // 服务器模式:启动监听 _tcpServer = new TcpListener(IPAddress.Parse(IPAddress_str), Port); _tcpServer.Start(); IsListening = true; // 设置监听状态 // 立即触发监听状态事件 ServerListeningChanged?.Invoke(true); // 异步等待客户端连接 _tcpServer.BeginAcceptTcpClient(AcceptClientCallback, null); } } catch (Exception ex) { RecordError($"启动失败: {ex.Message}"); } } // 客户端连接回调 private void AcceptClientCallback(IAsyncResult ar) { try { _tcpClient = _tcpServer.EndAcceptTcpClient(ar); _stream = _tcpClient.GetStream(); _isRunning = true; StartReceiving(); // 客户端连接触发连接状态 ConnectionStateChanged?.Invoke(true); } catch (Exception ex) { RecordError($"客户端连接失败: {ex.Message}"); } } /// <summary> /// 关闭TCP连接 /// </summary> public void Close() { try { _isRunning = false; _stream?.Close(); _tcpClient?.Close(); if (!IsClientMode) { _tcpServer?.Stop(); } ConnectionStateChanged?.Invoke(false); RecordStatus("连接已关闭"); } catch (Exception ex) { RecordError($"关闭异常: {ex.Message}"); } // 重置监听状态 if (!IsClientMode && IsListening) { IsListening = false; ServerListeningChanged?.Invoke(false); } } /// <summary> /// 发送数据 /// </summary> public void Send(string data) { if (!IsOpen || string.IsNullOrEmpty(data)) return; try { byte[] buffer = Encoding.UTF8.GetBytes(data); _stream.Write(buffer, 0, buffer.Length); _stream.Flush(); } catch (Exception ex) { RecordError($"发送失败: {ex.Message}"); Close(); // 发生错误时自动关闭连接 } } // 启动接收线程 private void StartReceiving() { _receiveThread = new Thread(() => { byte[] buffer = new byte[4096]; while (_isRunning && IsOpen) { try { if (_stream.DataAvailable) { int bytesRead = _stream.Read(buffer, 0, buffer.Length); if (bytesRead > 0) { string received = Encoding.UTF8.GetString(buffer, 0, bytesRead); ReceivedData = received; DataReceived?.Invoke(received); } } Thread.Sleep(50); // 降低CPU占用 } catch (IOException ex) when (ex.InnerException is SocketException) { RecordError($"连接异常中断: {ex.Message}"); Close(); break; } catch (Exception ex) { RecordError($"接收错误: {ex.Message}"); Thread.Sleep(1000); } } }) { IsBackground = true }; _receiveThread.Start(); } // 错误记录方法 private void RecordError(string message) { LastError = $"[{DateTime.Now:HH:mm:ss}] {message}"; ErrorOccurred?.Invoke(LastError); } private void RecordStatus(string message) { } } } 以下是Form1.cs的代码:using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO.Ports; using System.Linq; using System.Reflection.Emit; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.Net.Sockets; namespace _20250721test类 { public partial class Form1 : Form { private SerialPortManager sPortManager = new SerialPortManager(); // 在窗体类中声明通信对象 private TcpCommunication _tcpComm = new TcpCommunication(); public Form1() { InitializeComponent(); sPortManager.DataReceived += UpdateReceivedData; } private void Form1_Load(object sender, EventArgs e) { btn_openClose.Text = "打开"; lbl_connState.Text = "断开"; lbl_connState.BackColor = Color.Red; string[] portNames = SerialPort.GetPortNames(); // 获取所有可用串口的名字[^3] foreach (string portName in portNames) { cbo_com.Items.Add(portName); // 将每个串口名字添加到组合框中[^4] } // 绑定事件 _tcpComm.DataReceived += OnDataReceived; _tcpComm.ConnectionStateChanged += OnConnectionStateChanged; _tcpComm.ErrorOccurred += OnErrorOccurred; // 注册新事件 _tcpComm.ServerListeningChanged += OnServerListeningChanged; _tcpComm.ConnectionStateChanged += OnConnectionStateChanged; // 初始状态 UpdateUIState(); // 初始化控件 txt_IPaddress.Text = "127.0.0.1"; txt_IPport.Text = "5000"; cbo_IPClientServer.SelectedIndex = 0; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { _tcpComm.Close(); sPortManager.Close(); } private void btn_openClose_Click(object sender, EventArgs e) { if (btn_openClose.Text == "打开") { try { // 停止位转换(兼容C# 7.3) StopBits stopBits; switch (cbo_stopBit.Text) { case "1": stopBits = StopBits.One; break; case "1.5": stopBits = StopBits.OnePointFive; break; case "2": stopBits = StopBits.Two; break; default: stopBits = StopBits.One; break; } // 校验位转换(兼容C# 7.3) Parity parity; switch (cbo_parity.Text) { case "无": parity = Parity.None; break; case "奇校验": parity = Parity.Odd; break; case "偶校验": parity = Parity.Even; break; default: parity = Parity.None; break; } sPortManager.Open( cbo_com.Text, int.Parse(cbo_baudRate.Text), int.Parse(cbo_databit.Text), stopBits, parity, cbo_receiveEnd.Text ); if (sPortManager.IsOpen) { btn_openClose.Text = "关闭"; lbl_connState.Text = "连接"; lbl_connState.BackColor = Color.Lime; } } catch { MessageBox.Show("串口连接失败"); } } else { sPortManager.Close(); btn_openClose.Text = "打开"; lbl_connState.Text = "断开"; lbl_connState.BackColor = Color.Red; } } private void btn_send_Click(object sender, EventArgs e) { sPortManager.Send(txt_sendData.Text); } private void UpdateReceivedData(string data) { if (lbl_sPreceive.InvokeRequired) { lbl_sPreceive.Invoke(new Action(() => lbl_sPreceive.Text = data)); } else { lbl_sPreceive.Text = data; } } private void btn_IPopenClose_Click(object sender, EventArgs e) { if (_tcpComm.IsClientMode) { // 客户端模式逻辑不变 if (!_tcpComm.IsOpen) { _tcpComm.IPAddress_str = txt_IPaddress.Text; _tcpComm.Port = int.Parse(txt_IPport.Text); _tcpComm.IsClientMode = (cbo_IPClientServer.SelectedItem.ToString() == "Client"); _tcpComm.Open(); } else _tcpComm.Close(); } else { // 服务器模式:根据监听状态切换 if (!_tcpComm.IsListening) { _tcpComm.IPAddress_str = txt_IPaddress.Text; _tcpComm.Port = int.Parse(txt_IPport.Text); _tcpComm.IsClientMode = (cbo_IPClientServer.SelectedItem.ToString() == "Server"); _tcpComm.Open(); // 启动监听 } else _tcpComm.Close(); // 停止监听 } } private void beiyong() { if (!_tcpComm.IsOpen) { // 配置参数 _tcpComm.IPAddress_str = txt_IPaddress.Text; _tcpComm.Port = int.Parse(txt_IPport.Text); _tcpComm.IsClientMode = (cbo_IPClientServer.SelectedItem.ToString() == "Client"); // 打开连接 _tcpComm.Open(); } else { _tcpComm.Close(); } } private void btn_IPsend_Click(object sender, EventArgs e) { string data = txt_IPsendData.Text; if (!string.IsNullOrEmpty(data)) { _tcpComm.Send(data); } } // 窗体状态处理 private void OnServerListeningChanged(bool isListening) { this.Invoke((MethodInvoker)delegate { if (!_tcpComm.IsClientMode) { // 服务器监听状态更新 lbl_IPconnState.Text = isListening ? "监听中..." : "已断开"; lbl_IPconnState.BackColor = isListening ? Color.Yellow : Color.Red; if (isListening == true) { LogToTextBox("服务器模式-监听中..."); } else if (isListening == false) { LogToTextBox("服务器模式-已断开"); } btn_IPopenClose.Text = isListening ? "停止监听" : "开始监听"; } }); } // 事件处理方法 private void OnDataReceived(string data) { // 跨线程更新UI this.Invoke((MethodInvoker)delegate { lbl_IPreceive.Text = data; txt_IPreceiveLog.AppendText($"[接收] {DateTime.Now:HH:mm:ss}: {data}{Environment.NewLine}"); }); } private void OnConnectionStateChanged(bool isConnected) { this.Invoke((MethodInvoker)delegate { if (_tcpComm.IsClientMode) { // 客户端模式 lbl_IPconnState.Text = isConnected ? "已连接" : "已断开"; lbl_IPconnState.BackColor = isConnected ? Color.Lime : Color.Red; if (isConnected == true) { LogToTextBox("客户端模式-已连接"); } else if (isConnected == false) { LogToTextBox("客户端模式-已断开"); } btn_IPopenClose.Text = isConnected ? "关闭连接" : "打开连接"; } else { // 服务器模式:已连接客户端 if (isConnected) { lbl_IPconnState.Text = "已连接 (1客户端)"; lbl_IPconnState.BackColor = Color.Lime; LogToTextBox("服务器模式-已连接"); } // 监听状态由OnServerListeningChanged单独处理 } }); } // 统一UI状态更新 private void UpdateUIState() { if (_tcpComm.IsClientMode) { // 客户端模式初始状态 lbl_IPconnState.Text = "已断开"; lbl_IPconnState.BackColor = Color.Red; btn_IPopenClose.Text = "打开连接"; } else { // 服务器模式初始状态 lbl_IPconnState.Text = "未监听"; lbl_IPconnState.BackColor = Color.Red; btn_IPopenClose.Text = "开始监听"; } } private void OnErrorOccurred(string error) { this.Invoke((MethodInvoker)delegate { txt_ErrorLog.AppendText($"{error}{Environment.NewLine}"); MessageBox.Show($"通信错误: {error}", "系统警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); }); } private void LogToTextBox(string message) { if (txt_ErrorLog.InvokeRequired) { txt_ErrorLog.Invoke(new Action(() => { txt_ErrorLog.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\n"); txt_ErrorLog.ScrollToCaret(); })); } else { txt_ErrorLog.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\n"); txt_ErrorLog.ScrollToCaret(); } } } } 注意界面的txt、cbo、lbl控件已经存在的
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值