一·效果展示

源码派送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(); //释放资源
}
}
}

四·源码下载

MiniQQ1.1

本Demo仅仅实现了客户端互相打视频,更多更丰富的功能将在高版本中逐步为大家展示,欢迎大家持续关注哦!

如果您觉得对您有点帮助的话请点个赞吧!

循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)的更多相关文章

  1. 循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天

    <循序渐进做项目系列迷你QQ篇>将陆续介绍客户端聊天,文件传输,加好友,群聊,包括语音聊天,视频聊天,远程桌面等等需求如何实现,感兴趣的朋友可以持续关注.考虑到某些需求较为复杂,本系列采用 ...

  2. 循序渐进做项目系列(2):最简单的C/S程序——消息异步调用与消息同步调用

    上篇博客 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法 实现了一个最简单的C/S程序,即让服务器来做加法.当时为了通俗易懂采用了消息异步调用的方式.今天我们要采用消息同步调用的方式 ...

  3. 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法

    (本文是专门针对未接触过C/S开发的初学者而写的,C/S开发高手请自动忽略啊~~) 还在写“Hello world!”式的单机程序吗?还在各种拖控件吗?是否自己都觉得有点low呢?来个质的飞跃吧!看看 ...

  4. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(24)-权限组的设计和实现(附源码)(终结)

    ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装    ...

  5. C# 30分钟完成百度人脸识别——进阶篇(文末附源码)

    距离上次入门篇时隔两个月才出这进阶篇,小编惭愧,对不住关注我的卡哇伊的小伙伴们,为此小编用这篇博来谢罪. 前面的准备工作我就不说了,注册百度账号api,创建web网站项目,引入动态链接库引入. 不了解 ...

  6. C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 一点感想 很意外的,第一 ...

  7. 我们一起学习WCF 第一篇初识WCF(附源码供对照学习)

    前言:去年由于工作需要我学习了wcf的相关知识,初期对wcf的作用以及为何用怎么样都是一知半解,也许现在也不是非常的清晰.但是通过项目对wcf的运用在脑海里面也算有了初步的模型.今天我就把我从开始wc ...

  8. 循序渐进做项目系列(5):制作安装包,谁人都可以!——VS制作安装包简明教程

    一开始让我做安装包的时候,其实我是拒绝的.因为我根本就不会做安装包.查了资料之后,我很懵,很晕,很乱,因为不清晰,不简明,不直白.然而经过一番彷徨的挣扎,我终于发现:制作安装包,谁人都可以!故挥狼毫, ...

  9. arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

随机推荐

  1. 【HTML5】 web上的音频

    <!-- audio通过属性的设置可以控制音频播放的行为: 表6-2 audio元素的属性 ——————————————————————————————————————————————————— ...

  2. Python-匿名函数

    lambda 函数是一种快速定义单行的最小函数,可以用在任何需要函数的地方   常规版本: def fun(x,y) return x*y lambda版本: r = lambda x,y:x*y p ...

  3. Nginx - Linux下按天分割日志

    待完善. 可参考:https://www.iteblog.com/archives/1244

  4. JavaScript isNaN() 函数

    定义与用法: isNaN() 函数用于检查其参数是否是非数字值. 语法: isNaN(x) 描述:     x是要检测的值. 返回值: 如果 x 是特殊的非数字值 NaN(或者能被转换为这样的值),返 ...

  5. linux安装oracle11g

    准备oracle安装文件 Oracle11gR2包含两个文件linux_11gR2_database_1of2.zip和linux_11gR2_database_2of2.zip,将这两个文件通过SS ...

  6. How to make your assembly more secure from referencing by unauthorized bits

    Now the security has a trend to become more and more important in our daily work, hence I did some r ...

  7. WPF-系统托盘

    WPFSystemTray.cs public class WPFSystemTray { /// <summary> /// 设置系统托盘 /// </summary> // ...

  8. ssh简化后之事务管理

    为了能让大家更好的了解,所以今天跟大家分享整个项目.ps:ssh环境的搭建我就不一一讲解了,请大家参考 http://www.cnblogs.com/zczc1996/p/5842367.html. ...

  9. angluar去掉url中#

    众所周知,angular项目中路由机制会在地址栏加一个#来实现各个页面的切换,虽然url中有个#号也无伤大雅,但每次看到多一个这个东西总是不舒服(我不是强迫证啊),趁着项目间隙还是决定把它去掉. 去谷 ...

  10. NSCache和NSURLCache、网络缓存优化

    本文目录 一种缓存优化方案 响应头'Last-Modified'和请求头'If-Modified-Since' 'Keep-Alive'响应头和不离线的URLSession 'Expires'响应头 ...