原标题:winform项目——仿QQ即时通讯程序12:服务端程序补充及优化

上一篇文章大概完成了服务端程序,今天继续做项目的时候发现还有一些功能没有做,还有几处地方不够完善。不做好就会影响客户端程序的编写,因此,本篇文章将对服务端程序进行补充和优化。

首先是未完成的功能:离线消息的检测与发送

用户连接到服务器之后,不仅要开启线程接收、转发消息,也要检测数据库中是否有离线消息,如果有就发送给用户并将离线消息删除。

思路:根据上线的用户账号,查找离线消息表,找到记录就发送给用户,然后将数据库记录删除即可。在昨天的开启接收消息转发消息的代码下面,继续开启检测离线消息的线程:

//检测是否有离线消息,如果有就发送到客户端

Thread check = new Thread(checkUnReceivemsg);

check.Start(Account);

然后是checkUnReceivemsg方法:

private void checkUnReceivemsg(object clientAccount)

{

string toAccount = clientAccount.ToString();

//根据该上线的账号查找是否有离线消息

SqlDataReader sdr = SqlHelper.ExecuteReader("select * from Temp_msg where ToAccount='" + toAccount + "'");

while(sdr.Read())

{

if (dic_socket.ContainsKey(toAccount))

{

//给该账号发送所有的普通离线消息

if(sdr[4].ToString().Trim() != "")

{

dic_socket[toAccount].Send(Encoding.UTF8.GetBytes(sdr[2].ToString().Trim() + splitFlag + sdr[3].ToString().Trim()+splitFlag+sdr[4].ToString().Trim()));

}

else

{

//发送离线的验证消息

dic_socket[toAccount].Send(Encoding.UTF8.GetBytes(sdr[2].ToString().Trim() + splitFlag + sdr[3].ToString().Trim()));

}

}

}

sdr.Close();

//发送完毕之后删除该账号的离线消息

SqlHelper.ExecuteSql("delete from Temp_msg where ToAccount='"+toAccount+"'");

}

注意这个方法里面的发送消息的方式,这里用了一个if判断该消息是普通聊天消息还是验证消息。这里涉及到一个核心的消息模型。

CIM消息模型

我们作为程序的创造者,在这里将CIM程序中所有涉及到的消息分为两类:普通消息和验证消息。为了区分这两类消息,我们定义了一个规则,普通消息发送的时候,带有三种属性:对方账号、消息内容和时间,而验证消息则去掉了时间,只带有对方账号和验证消息内容。这个规则是固定的。因此后面做到客户端接收消息的时候,也要根据这个规则去判断消息类型。

针对这个规则,我们需要对上一篇文章的服务端代码的receiveAndSend方法进行了一些修改,修改后的代码如下:

private void receiveAndsend(object clientAccount)

{

//服务端核心功能:接收消息并转发消息

//将object变成string 方便使用

string fromAccount = clientAccount.ToString();

try

{

//死循环保证能一直接收消息

while (true)

{

byte[] buffer = new byte[1024];

int len = dic_socket[fromAccount].Receive(buffer);

//接收到的普通消息含有三段,前一段是目标账号,后一段是内容,再后面是时间

string msg = Encoding.UTF8.GetString(buffer, 0, len);

//将两段消息分隔开

string[] msgarr = msg.Split(new string[] { splitFlag }, StringSplitOptions.None);

if(msgarr.Length == 3)

{//普通消息

string toAccount = msgarr[0];

string content = msgarr[1];

string time = msgarr[2];

//利用目标账号对字典进行检测,如果存在表示目标用户在线,可以转发

if (dic_socket.ContainsKey(toAccount))

{

//对方在线

dic_socket[toAccount].Send(Encoding.UTF8.GetBytes(fromAccount + splitFlag + content + splitFlag + time));

}

else

{

//对方不在线 将消息保存在离线消息临时表中

SqlHelper.ExecuteSql("insert into Temp_msg (ToAccount,FromAccount,MsgContent,Time) values ('" + toAccount + "','" + fromAccount + "','" + content + "','" + time + "')");

}

}else if(msgarr.Length == 2)

{

//验证消息

string toAccount = msgarr[0];

string content = msgarr[1];

//利用目标账号对字典进行检测,如果存在表示目标用户在线,可以转发

if (dic_socket.ContainsKey(toAccount))

{

//对方在线

dic_socket[toAccount].Send(Encoding.UTF8.GetBytes(fromAccount + splitFlag + content));

}

else

{

//对方不在线 将消息保存在离线消息临时表中

SqlHelper.ExecuteSql("insert into Temp_msg (ToAccount,FromAccount,MsgContent) values ('" + toAccount + "','" + fromAccount + "','" + content + "')");

}

}

}

}

catch (Exception ee)

{

//发生此异常是因为客户端连接断开,将这种异常认为是正常操作即可

//在这里当做客户端下线即可

if (dic_socket.ContainsKey(fromAccount))

{

dic_socket.Remove(fromAccount);

upAnddown.AppendText("账号" + fromAccount + "在" + DateTime.Now.ToString() + "下线\r\n");

label3.Text = (int.Parse(label3.Text) - 1).ToString();

online_list.Items.Remove(fromAccount);

}

}

}

可以看到,代码中新增了区分两种类型消息的逻辑。还有一点需要提及,前期我们分析数据库的时候,建立了一张验证消息表,那么按照我们今天的逻辑,将不再需要用另一个表去存储验证消息了,离线的验证消息当做普通消息处理,只不过最后的time字段不需要存储东西即可。验证消息的历时记录就存放在本地文件中,可以减轻服务器负担。

服务端程序编者已经测试运行了一下午,一直都没有停止运行,说明还是挺稳定的,上下线记录功能也能够正常工作。

好了,到目前为止,服务端程序算是真正做完了,下一篇文章将介绍客户端登录之后的初始化操作。

本文系小博客网站原创,转载请注明文章链接地址返回搜狐,查看更多

责任编辑:

winform服务器消息推送,winform项目——仿QQ即时通讯程序12:服务端程序补充及优化...相关推荐

  1. winform项目_winform项目——仿QQ即时通讯程序01:原理及项目分析

    即时通讯程序,腾讯QQ可以说是一家独大,虽然市场上仍然有类似QQ的即时通讯程序,但是基本上面向的对象都是特定人群.那么,现在做一个即时通讯的软件还有意义吗?在我看来,意义非常大.作为一个学习编程的人, ...

  2. .net winform panel 不刷新_winform项目——仿QQ即时通讯程序04:登录界面补充

    上一篇文章给出了Login登录界面的详细制作过程,目的是让初学者体验如何对窗体上的控件进行布局,过程非常详细,如果对winform布局不熟悉的同学可以详细阅读.本篇文章将继续完成Login窗体上的注册 ...

  3. delphi 登录界面 主窗体 切换_winform项目——仿QQ即时通讯程序06:主界面交互逻辑...

    上一篇文章,我们搭建好了主界面的布局.本文将实现页面的交互逻辑,比如如何移动窗体.调整窗体大小.点击消息和联系人切换下方的panel面板.动态加载消息列表panel和好友列表panel等,并且左下角的 ...

  4. c# webclient 保存会话信息_winform项目——仿QQ即时通讯程序16:会话列表的存储

    上一篇文章完成了验证消息的接收,这篇文章本打算做好友间互发消息,但是做的时候发现会话列表的存储还没做.就是会话列表中有会话的情况下,关闭了软件,然后再次登录后,应该要复现会话列表.因此本篇文章将实现会 ...

  5. tornado服务器动态文件,tornado 实现服务器消息推送功能

    这篇文章介绍tornado 服务器消息推送功能服务器端与客户端实现的的方法. 消息推送的过程: 客户端1 连接请求,服务器先hold 住,别返回: 客户端2 发送消息,服务器把信息返回给 客户端1. ...

  6. 基于环信的仿QQ即时通讯的简单实现

    代码地址如下: http://www.demodashi.com/demo/11645.html 我的博客地址 之前一直想实现聊天的功能,但是感觉有点困难,今天看了环信的API,就利用下午的时间动手试 ...

  7. ionic 服务器消息推送,Ionic3 本地消息推送

    项目上有一个消息推送的功能,一开始想使用极光推送,在安卓上测试比较顺利,但是IOS上需要什么证书,没有开发者账号,感觉好麻烦.后面就想在每次启动app的时候,本地推送一次消息,碰巧官网上发现了这个插件 ...

  8. 钉钉 服务器 消息推送,【20210727 更新】 全能推送PushBot(原钉钉推送)支持企业微信,PushPlus,Bark...

    本帖最后由 然后七年 于 2021-7-27 21:51 编辑 公告: 自2021年04月25日起,本项目luci-app-serverchand改名为luci-app-pushbot 全能推送. o ...

  9. sse java8_HTTP 服务器消息推送之SSE

    HTTP 服务器推送也称 HTTP 流,是一种客户端-服务器通信模式,它将信息从 HTTP 服务器异步推送到客户端,而无需客户端请求.现在的 web 和 app 中,越来越多的场景使用这种通信模式,比 ...

最新文章

  1. 常用的数据结构-散列表
  2. redis和memecache有什么区别?
  3. VTK:Utilities之ColorLookupTable
  4. 41. First Missing Positive 缺失的第一个正数
  5. EditPlus注册码在线生成,强大
  6. python简述文件目录相对路径_【Python】 配置文件相对路径软件自动执行的工作目录...
  7. BCrypt管理员登录密码验证
  8. centos怎么用命令行启动mysql_centos怎么用命令行启动mysql数据库
  9. mysql 内连接与外连接的区别
  10. Java实习日记(1)
  11. Android自定义View 顶部导航栏
  12. excel如何随机生成不重复的数字
  13. 单调栈-leetcode-739. 每日温度
  14. mysql数据库安装错误报错Falled不成功,感叹号
  15. 与华为SIP硬终端(TE40)对接注意事项
  16. 2019「友盟杯」数据分析大赛结果公布
  17. 什么是生化分析中的反应曲线?
  18. [javascript] js删除数组中的元素
  19. 清除文件计算机病毒是,删除电脑病毒文件System Volume Information的方法
  20. linux整盘封装生成iso,一键自安装ISO封装打包脚本 | 聂扬帆博客

热门文章

  1. 渗透测试或安服等面试问题与答案
  2. 剑灵最新服务器2017,剑灵合区2017 | 手游网游页游攻略大全
  3. 华为mate40价格曝光
  4. http强制升级为https http头文件 Content Security Policy: 升级不安全的请求
  5. 网站推荐:11个相似图片搜索网站(以图找图)
  6. android 虚线圆角矩形框,android 画虚线、实线,画圆角矩形,一半圆角
  7. jquery给单选按钮赋值_jquery循环遍历radio单选按钮,并设置选中状态
  8. 美国政府结束停摆 但其对加密货币采用的损害将长期存在(中篇)
  9. STM32读取MQ4传感器、DHT11温湿度传感器、GP2Y1014AU0F夏普光学灰尘传感器数据
  10. 苹果手机适配手写代码