《循序渐进做项目系列迷你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)——实现客户端互相聊天的更多相关文章

  1. 循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)

    一·效果展示 源码派送:MiniQQ1.1 文字聊天的实现参见:循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天 二·服务端设计 对于实现视频聊天而言,服务端最核心的工作就是要构造多媒 ...

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

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

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

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

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

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

  5. 一步一步使用ABP框架搭建正式项目系列教程之本地化详解

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...

  6. 七天接手react项目 系列 —— react 路由

    其他章节请看: 七天接手react项目 系列 react 路由 本篇首先讲解路由原理,接着以一个基础路由示例为起点讲述路由最基础的知识,然后讲解嵌套路由.路由传参,最后讲解路由组件和一般组件的区别,以 ...

  7. 产品相关 做产品VS做项目

    做产品VS做项目 by:授客 QQ:1033553122 相关定义 根据GB/T19000—2008<质量管理体系基础和术语>,有以下定义 过程process 一组将输入转化为输出的相互关 ...

  8. ABP框架搭建项目系列教程基础版完结篇

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...

  9. 七天接手react项目 系列 —— 尾篇(antd 和 mobx)

    其他章节请看: 七天接手react项目 系列 尾篇 前面我们依次学习了 react 基础知识.react 脚手架创建项目.react 路由,已经花费了不少时间,但距离接手 spug_web 项目还有一 ...

随机推荐

  1. Python 修改电脑DNS

    Pc电脑一般连网都是动态DHCP获取局域的IP地址,而且DNS服务器为自动获取地址.要修改DNS就要打开本地网络-本地连接- 属性- TCP/IP 手动修改DNS. 其实Python也可以通过WMI接 ...

  2. PostgreSQL中标准的SQL boolean数据类型

  3. IMEI串号

    IMEI串号就是国际移动设备身份码,是电子设备的唯一身份证,由于它的唯一性,它可以用来查询电子设备的保修期还有产地,可以说用处直逼人民的身份证啊! 在拨号键盘页面  输入[*#06#]五个字符

  4. #英文#品读中国城市个性——秦汉雄风&和祖先在一起

    妨碍 interfere with 仇恨 hatred ​坍塌 collapse 专制君主 autocratic dictator 排除异己 suppress opposition 被逼到绝望边缘 b ...

  5. #英文#品读中国城市个性——最好的和最坏的&当东方遇到西方

    冒险家的乐园 a playground of risk 实现发财梦 realize one's dreams of wealth 道德沦丧,堕落 moral deprivation 租界 foreig ...

  6. .NET 项目代码风格要求

    原文:http://kb.cnblogs.com/page/179593/ 项目代码风格要求 PDF版下载:项目代码风格要求V1.0.pdf 代码风格没有正确与否,重要的是整齐划一,这是我拟的一份&l ...

  7. 《UML大战需求分析》阅读随笔(六)

    在我们做的代码设计中分为系统设计和程序设计.程序设计是系统设计中模拟程序的执行逻辑,定义客户机服务器对象合作的框架的那个部分.程序和事务设计中,作者讲述到程序和事务设计将系统设计制品放在一起,并作为系 ...

  8. JS冒泡排序(div)

    更生动的排序动画. 通过改变div的高度来实现排序,通过闭包来实现for循环的睡眠时间. <!doctype html> <html lang="en"> ...

  9. d-规则

    [问题描述]对任意给定的m(m∈N+)和n(n∈N+),满足m<n,构造一初始集合:P={x|m≤x≤n,x∈N+} (m,n≤100).现定义一种d规则如下:若存在a∈P,且存在K∈N+ ,K ...

  10. Idea中包内中的置文件如何发布到编译后的目录中去

    1.问题引入: 运行一个maven+springmvc+hibernate的项目的时候出现了下边的错误: Caused by: java.io.FileNotFoundException: class ...