循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)
一·效果展示

源码派送:MiniQQ1.1
文字聊天的实现参见:循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天
二·服务端设计
对于实现视频聊天而言,服务端最核心的工作就是要构造多媒体服务器MultimediaServer 。
namespace Server
{
static class Program
{
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//创建服务端通信引擎
IRapidServerEngine ServerEngine = RapidEngineFactory.CreateServerEngine();
ServerHandler serverHandler = new ServerHandler();//创建服务端消息处理器
//初始化服务端引擎,设置好用于监听的端口号,并注入消息处理器
ServerEngine.Initialize(/*端口号*/, serverHandler); DefaultUserVerifier userVerifier = new DefaultUserVerifier();//默认任何用户都验证通过
//OMCS配置信息
OMCSConfiguration config = new OMCSConfiguration(/*摄像头采集的帧频*/,
/*远程桌面的帧频*/,
EncodingQuality.Middle/*语音编码的质量*/);
//创建多媒体服务器
IMultimediaServer MultimediaServer = MultimediaServerFactory.CreateMultimediaServer(/*监听的端口*/,
userVerifier/*用户帐密验证器*/,
config/*OMCS配置信息*/,
false/*是否记录详细的安全日志*/);
Application.Run(new Form_Server()); }
}
}
三·客户端设计
对于实现视频聊天而言,客户端设计的核心在于需要构造并初始化多媒体设备管理器 multimediaManager。
1.登陆窗设计
对于实现视频聊天而言,登陆窗的主要任务就是与多媒体服务器MultimediaServer 建立连接,并初始化本地多媒体管理器multimediaManager。
namespace Client
{
public partial class Form_Login : Form
{
private IRapidPassiveEngine clientEngine;//客户端通信引擎 private ClientHandler clientHandler;//客户端消息处理器 public string SelfUserID//本人用户ID,该属性主要是为了暴露给主窗体用来标识用户
{
get { return this.textBox_UserID.Text; }
} public Form_Login(IRapidPassiveEngine _clientEngine, ClientHandler _clientHandler)
{
InitializeComponent();
//传入通信引擎和消息处理器主要是为了登陆的时候进行通信引擎初始化操作
this.clientEngine = _clientEngine;
this.clientHandler = _clientHandler;
} private void button_login_Click(object sender, EventArgs e)
{
//通信引擎初始化,与目标服务器建立TCP连接
LogonResponse logonResponse = this.clientEngine.Initialize(this.textBox_UserID.Text, this.textBox_Password.Text, "127.0.0.1", , clientHandler);
//创建多媒体设备管理器
IMultimediaManager multimediaManager = MultimediaManagerFactory.GetSingleton();
multimediaManager.CameraDeviceIndex = ;//要使用的摄像头的索引
multimediaManager.AutoAdjustCameraEncodeQuality = false;//是否根据音频反馈以及视频丢帧情况自动调整视频编码质量
//与多媒体服务器建立连接,并初始化本地多媒体管理器。
multimediaManager.Initialize(this.textBox_UserID.Text,/*当前登录的用户ID*/
null,/*当前登录的用户的密码*/
"127.0.0.1",/*OMCS服务器IP*/
);/*OMCS服务器端口*/
if (logonResponse.LogonResult == LogonResult.Succeed)
{
this.DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show("登陆失败!" + logonResponse.LogonResult.ToString() + logonResponse.FailureCause);
}
}
}
}
2.主窗体设计
对于实现视频聊天而言,主窗体最主要的工作就是开启视频窗。
namespace Client
{
public partial class Form_Client : Form
{
private IRapidPassiveEngine clientEngine; private string selfUserID;
private string targetUserID; public Form_Client(IRapidPassiveEngine _clientEngine,string _selfUserID)
{
this.clientEngine = _clientEngine;
this.selfUserID = _selfUserID;
this.Text = _selfUserID;//在窗体上显示本用户ID
InitializeComponent();
} private void button_Send_Click(object sender, EventArgs e)
{
string msg = this.textBox_Input.Text;//聊天消息
Byte[] msgCode = Encoding.UTF8.GetBytes(msg);//转码以备发送
//从输入框读取待发送用户ID
//利用通信引擎发送消息
this.clientEngine.CustomizeOutter.Send(this.targetUserID, InformationType.Chat, msgCode);
this.ShowChatMsg(this.selfUserID, msg);
}
//将聊天消息按一定格式显示在界面上
public void ShowChatMsg(string UserID, string msg)
{
this.richTextBox_Output.AppendText(UserID + " " + DateTime.Now.ToString() + "\n");
this.richTextBox_Output.AppendText(msg + "\n");
this.richTextBox_Output.ScrollToCaret();
this.textBox_Input.Text = "";
}
//开启视频
private void button_Video_Click(object sender, EventArgs e)
{
this.targetUserID = this.textBox_TargetUserID.Text;
Form_Video form_Video = new Form_Video(this.targetUserID/*待连接用户ID*/);//创建视频窗
form_Video.Show();//显示视频窗
}
}
}
3.视频窗设计
对于实现视频聊天而言,视频窗最主要的任务就是将视频连接器cameraConnector连接到目标用户的摄像头
namespace Client
{
public partial class Form_Video : Form
{
public Form_Video(string targetUserID)
{
InitializeComponent();
//预定摄像头连接器的连接结束和连接断开事件
this.cameraConnector.ConnectEnded += new ESBasic.CbGeneric<OMCS.Passive.ConnectResult>(cameraConnector_ConnectEnded);
this.cameraConnector.Disconnected += new ESBasic.CbGeneric<OMCS.Passive.ConnectorDisconnectedType>(cameraConnector_Disconnected);
this.cameraConnector.BeginConnect(targetUserID/*待连接用户ID*/);//尝试连接目标多媒体设备
} void cameraConnector_Disconnected(OMCS.Passive.ConnectorDisconnectedType connectorDisconnectedType)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new CbGeneric<ConnectorDisconnectedType>(this.cameraConnector_Disconnected), connectorDisconnectedType);
}
else
{
this.Text = string.Format("视频:断开,{0}", connectorDisconnectedType);
if (connectorDisconnectedType == ConnectorDisconnectedType.TrialTimeout)
{
MessageBox.Show("Trial Timeout");
}
}
} void cameraConnector_ConnectEnded(ConnectResult result)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new CbGeneric<ConnectResult>(this.cameraConnector_ConnectEnded), result);
}
else
{
//显示视频连接结果
this.Text = string.Format("视频:{0}", result == ConnectResult.Succeed ? "正常" : result.ToString());
}
} //关闭窗口时,主动断开连接,并释放连接器
private void Form_Video_FormClosed(object sender, FormClosedEventArgs e)
{
this.cameraConnector.Disconnect();//与目标用户的多媒体设备断开连接
this.cameraConnector.Dispose(); //释放资源
}
}
}
四·源码下载
本Demo仅仅实现了客户端互相打视频,更多更丰富的功能将在高版本中逐步为大家展示,欢迎大家持续关注哦!
如果您觉得对您有点帮助的话请点个赞吧!
循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)的更多相关文章
- 循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天
<循序渐进做项目系列迷你QQ篇>将陆续介绍客户端聊天,文件传输,加好友,群聊,包括语音聊天,视频聊天,远程桌面等等需求如何实现,感兴趣的朋友可以持续关注.考虑到某些需求较为复杂,本系列采用 ...
- 循序渐进做项目系列(2):最简单的C/S程序——消息异步调用与消息同步调用
上篇博客 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法 实现了一个最简单的C/S程序,即让服务器来做加法.当时为了通俗易懂采用了消息异步调用的方式.今天我们要采用消息同步调用的方式 ...
- 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法
(本文是专门针对未接触过C/S开发的初学者而写的,C/S开发高手请自动忽略啊~~) 还在写“Hello world!”式的单机程序吗?还在各种拖控件吗?是否自己都觉得有点low呢?来个质的飞跃吧!看看 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(24)-权限组的设计和实现(附源码)(终结)
ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框架搭建 (2):数据库访问层的设计Demo (3):面向接口编程 (4 ):业务逻辑层的封装 ...
- C# 30分钟完成百度人脸识别——进阶篇(文末附源码)
距离上次入门篇时隔两个月才出这进阶篇,小编惭愧,对不住关注我的卡哇伊的小伙伴们,为此小编用这篇博来谢罪. 前面的准备工作我就不说了,注册百度账号api,创建web网站项目,引入动态链接库引入. 不了解 ...
- C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 一点感想 很意外的,第一 ...
- 我们一起学习WCF 第一篇初识WCF(附源码供对照学习)
前言:去年由于工作需要我学习了wcf的相关知识,初期对wcf的作用以及为何用怎么样都是一知半解,也许现在也不是非常的清晰.但是通过项目对wcf的运用在脑海里面也算有了初步的模型.今天我就把我从开始wc ...
- 循序渐进做项目系列(5):制作安装包,谁人都可以!——VS制作安装包简明教程
一开始让我做安装包的时候,其实我是拒绝的.因为我根本就不会做安装包.查了资料之后,我很懵,很晕,很乱,因为不清晰,不简明,不直白.然而经过一番彷徨的挣扎,我终于发现:制作安装包,谁人都可以!故挥狼毫, ...
- arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
随机推荐
- ExtJs基础知识总结:自定义弹窗和ComboBox自动联想加载(四)
概述 Extjs弹窗可以分为消息弹窗.对话框,这些弹窗的方式ExtJs自带的Ext.Msg.alert就已经可以满足简单消息提示,但是相对复杂的提示,比如如何将Ext.grid.Panel的控件显示嵌 ...
- 设计模式之单例模式Singleton(三创建型)
1.什么事单例模式? 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须 ...
- 【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
一.动态SQL 什么是动态SQL,就是在不同的条件下,sql语句不相同的意思,曾经在“酒店会员管理系统”中写过大量的多条件查询,那是在SSH的环境中,所以只能在代码中进行判断,以下是其中一个多条件查询 ...
- 【Java EE 学习 76 上】【数据采集系统第八天】【角色授权】【用户授权】【权限的粗粒度控制】【权限的细粒度控制】
一.角色管理 单击导航栏上的"角色管理"超链接,跳转到角色管理界面,在该界面上显示所有角色,并提供角色的增加和删除.修改超链接. 1.增加新角色(角色授权) 流程:单击增加新角色超 ...
- Visual Studio高级调试技巧
1. 设置软件断点,运行到目标位置启动调试器 方法①:使用汇编指令(注:x64 c++不支持嵌入汇编) _asm 方法②:编译器提供的方法 __debugbreak(); 方法③:使用windows ...
- 百度UEditor在线编辑器的配置和图片上传
前言 最近在项目中使用了百度UEditor富文本编辑器,配置UEditor过程中遇到了几个问题,在此记录一下解决方案和使用方法,避免以后使用UEditor出现类似的错误. 基本配置 一.下载UEdit ...
- 用WinForm写的员工考勤项目!!!!!!
先说几句,作为一个还在学习的程序员,掌握的知识有限:但我利用自身所学,给一些像我一样还在学习的码农提供我的绵薄之力! 写的不好,但是尽力了,希望大牛指点.多多吐槽!!! 好了开始说项目需求: 实现新增 ...
- hellocharts的折线图与柱状图的结合之ComboLineColumnChartView
哼哼,网上找了半天都不全,所以决定自己写一个完整的可以直接贴代码的 test.xml <?xml version="1.0" encoding="utf-8&quo ...
- NMAP分布式扫描工具dnmap
NMAP分布式扫描工具dnmap NMAP是一款知名的网络扫描工具.它提供丰富和强大的网络扫描功能.但很多时候,需要渗透测试人员从多个终端发起扫描任务,以快速扫描大型网络,或规避IP限制等安全策略 ...
- 窗体Showmedol 遇到的奇怪异常: cannot make a visible window model
//窗体Showmedol 遇到的奇怪异常: cannot make a visible window model //背景:ShowModal A窗体,A窗体再ShowModal B窗体:A是透明背 ...