循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天
《循序渐进做项目系列迷你QQ篇》将陆续介绍客户端聊天,文件传输,加好友,群聊,包括语音聊天,视频聊天,远程桌面等等需求如何实现,感兴趣的朋友可以持续关注。考虑到某些需求较为复杂,本系列采用成熟的通信框架ESFramework来做,而不是从socket做起,当然这与本人才疏学浅也有莫大的关系,如果大家不嫌弃小弟写得太“low”,还请捧个人场,顺便给予鼓励!
言归正传,今天就是要实现一个最简单的功能:客户端互相聊天。
一·部署通信设备
参见 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IRapidPassiveEngine clientEngine = RapidEngineFactory.CreatePassiveEngine();//创建客户端通信引擎
ClientHandler clientHandler = new ClientHandler();//创建客户端消息处理器
Form_Login loginForm = new Form_Login(clientEngine, clientHandler);
loginForm.ShowDialog();//登陆窗会话完成才能运行主窗体
Form_Client clientForm = new Form_Client(clientEngine, loginForm.SelfUserID);
clientHandler.ClientForm = clientForm;
Application.Run(clientForm);
}
二·登陆窗设计
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);
if (logonResponse.LogonResult == LogonResult.Succeed)
{
this.DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show("登陆失败!" + logonResponse.LogonResult.ToString() + logonResponse.FailureCause);
}
}
}
三·客户端主窗体设计
public partial class Form_Client : Form
{
private IRapidPassiveEngine clientEngine; private string selfUserID; 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);//转码以备发送
string targetUserID = this.textBox_TargetUserID.Text;//从输入框读取待发送用户ID
//利用通信引擎发送消息
this.clientEngine.CustomizeOutter.Send(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 = "";
}
}
四·客户端收到消息后进行处理
public class ClientHandler: ICustomizeHandler
{
private Form_Client clientForm; //该属性是为了在外部将clientForm注入,之所以不在构造函数中传入是因为当时clientForm尚未创建
public Form_Client ClientForm
{
get { return clientForm; }
set { clientForm = value; }
} public void HandleInformation(string sourceUserID, int informationType, byte[] info)
{
if (informationType == InformationType.Chat)
{
if (this.clientForm.InvokeRequired) //不是主线程时
{
//转换为主线程
this.clientForm.Invoke(new ESBasic.CbGeneric<string, int, byte[]>(this.HandleInformation), sourceUserID, informationType, info);
}
else
{
string msg = Encoding.UTF8.GetString(info);//解析消息
this.clientForm.ShowChatMsg(sourceUserID, msg);//显示消息
}
}
} public byte[] HandleQuery(string sourceUserID, int informationType, byte[] info)
{
throw new NotImplementedException();
}
五·总结
源码下载:MiniQQ1.0.zip
由于代码中尽量做到规范命名,并做了详细的注释,所以没有再花更多的文字段落去说明,相信大家也能很容易看懂。整个逻辑十分简单,对于新手有两点需要注意一下:
1.各个类之间通过参数传递从而完成合作,传参方式有的是通过构造函数,有的是通过属性注入,新手朋友们可以自己比较一下两种方式的适用场合。
2.其中有一处重构,就是聊天的时候既要显示自己发的消息又要显示收到的消息,这时候代码基本上是一样的,所以我将其重构了。至于什么时候需要重构,如何重构,新手朋友们可以自己多多揣摩。
这两点都是平时做项目中经常遇到的问题,是需要熟练掌握的。
当然,最重要的一点还是循序渐进做项目咯!做的多了这些东西自然就会熟练了,写程序时就能够下笔如有神了!
循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天的更多相关文章
- 循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)
一·效果展示 源码派送:MiniQQ1.1 文字聊天的实现参见:循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天 二·服务端设计 对于实现视频聊天而言,服务端最核心的工作就是要构造多媒 ...
- 循序渐进做项目系列(2):最简单的C/S程序——消息异步调用与消息同步调用
上篇博客 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法 实现了一个最简单的C/S程序,即让服务器来做加法.当时为了通俗易懂采用了消息异步调用的方式.今天我们要采用消息同步调用的方式 ...
- 循序渐进做项目系列(1):最简单的C/S程序——让服务器来做加法
(本文是专门针对未接触过C/S开发的初学者而写的,C/S开发高手请自动忽略啊~~) 还在写“Hello world!”式的单机程序吗?还在各种拖控件吗?是否自己都觉得有点low呢?来个质的飞跃吧!看看 ...
- 循序渐进做项目系列(5):制作安装包,谁人都可以!——VS制作安装包简明教程
一开始让我做安装包的时候,其实我是拒绝的.因为我根本就不会做安装包.查了资料之后,我很懵,很晕,很乱,因为不清晰,不简明,不直白.然而经过一番彷徨的挣扎,我终于发现:制作安装包,谁人都可以!故挥狼毫, ...
- 一步一步使用ABP框架搭建正式项目系列教程之本地化详解
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...
- 七天接手react项目 系列 —— react 路由
其他章节请看: 七天接手react项目 系列 react 路由 本篇首先讲解路由原理,接着以一个基础路由示例为起点讲述路由最基础的知识,然后讲解嵌套路由.路由传参,最后讲解路由组件和一般组件的区别,以 ...
- 产品相关 做产品VS做项目
做产品VS做项目 by:授客 QQ:1033553122 相关定义 根据GB/T19000—2008<质量管理体系基础和术语>,有以下定义 过程process 一组将输入转化为输出的相互关 ...
- ABP框架搭建项目系列教程基础版完结篇
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...
- 七天接手react项目 系列 —— 尾篇(antd 和 mobx)
其他章节请看: 七天接手react项目 系列 尾篇 前面我们依次学习了 react 基础知识.react 脚手架创建项目.react 路由,已经花费了不少时间,但距离接手 spug_web 项目还有一 ...
随机推荐
- Jquery的$(selector).each()和$.each()原理和区别
我们都用过Jqurey中的each函数,都知道each()有两种方式去调用,一种是通过$.each()调用,另一种是$(selector).each()去调用,那么它们之间有什么区别? 翻看一下Jqu ...
- Python-Hello world!
一.Python安装 Windows 1.下载安装包 https://www.python.org/downloads/ 2.安装 默认安装路径:C:\python3.5 3.配置环境变量: [右键计 ...
- C语言的一些小知识
注:本文讨论的"C语言"为GNU C,而非ANSI C 标准库 语法 switch语句中的case关键词可以放在任何地方 switch (a) { case 1:; if (b== ...
- js获取css中的样式
众所周知,obj.style只能够获取 <div id="a" style="width:100px;"></div> 结构上的样式 如 ...
- Android自定义组件
[参考的原文地址] http://blog.csdn.net/l1028386804/article/details/47101387效果图: 实现方式: 一:自定义一个含有EditText和Butt ...
- 【CentOS】LNMP
本文为博主JerryChan所有,如需转载,请联系博主747618706@qq.com,并附上博客链接/////////////////目录//////////////////一.LNMP的安装 1. ...
- C#开发中常用方法2------json转DataTable
/// <summary>/// 将json转换为DataTable/// </summary>/// <param name="strJson"&g ...
- jQuery实战
1.获取标签在文档中的位置 var left = $('.selected').offset().left; var top = $('.selected').offset().top; 2.获取选中 ...
- 朴素贝叶斯算法下的情感分析——C#编程实现
这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Language Pr ...
- SOAPUI使用教程-REST服务和WADL
首先创建一个新的REST项目: 选择文件|新建项目REST从主菜单: 通常情况下,我们可能会只提供一个URI 点击导入消耗. 在新建项目消耗对话框: 点击浏览. 然后,我们可以浏览到该文件: 点击 ...