iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >C#的即时通信程序怎么实现
  • 398
分享到

C#的即时通信程序怎么实现

2023-06-17 09:06:32 398人浏览 安东尼
摘要

这篇文章主要介绍“C#的即时通信程序怎么实现”,在日常操作中,相信很多人在C#的即时通信程序怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#的即时通信程序怎么实现”的疑惑有所帮助!接下来,请跟着小编

这篇文章主要介绍“C#的即时通信程序怎么实现”,在日常操作中,相信很多人在C#的即时通信程序怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#的即时通信程序怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、即时通信系统

在我们的生活中经常使用即时通信的软件,我们经常接触到的有:QQ、阿里旺旺、MSN等等。这些都是属于即时通信(Instant Messenger,IM)软件,IM是指所有能够即时发送和接收互联网消息的软件。

在前面专题P2P编程中介绍过P2P系统分两种类型——单纯型P2P和混合型P2P(QQ就是属于混合型的应用),混合型P2P系统中的服务器(也叫索引服务器)起到协调的作用。在文件共享类应用中,如果采用混合型P2P技术的话,索引服务器就保存着文件信息,这样就可能会造成版权的问题,然而在即时通信类的软件中, 因为客户端传递的都是简单的聊天文本而不是网络媒体资源,这样就不存在版权问题了,在这种情况下,就可以采用混合型P2P技术来实现我们的即时通信软件。前面已经讲了,腾讯的QQ就是属于混合型P2P的软件。

因此本专题要实现一个类似QQ的聊天程序,其中用到的P2P技术是属于混合型P2P,而不是前一专题中的采用的单纯型P2P技术,同时本程序的实现也会用到tcp、UDP编程技术。具体的相关内容大家可以查看本系列的相关专题的。

二、程序实现的详细设计

本程序采用P2P方式,各个客户端之间直接发消息进行聊天,服务器在其中只是起到协调的作用,下面先理清下程序的流程:

2.1 程序流程设计

当一个新用户通过客户端登陆系统后,从服务器获取当在线的用户信息列表,列表信息包括系统中每个用户的地址,然后用户就可以单独向其他发消息。如果有用户加入或者在线用户退出时,服务器就会及时发消息通知系统中的所有其他客户端,达到它们即时地更新用户信息列表。

根据上面大致的描述,我们可以把系统的流程分为下面几步来更好的理解(大家可以参考QQ程序将会更好的理解本程序的流程):

用户通过客户端进入系统,向服务器发出消息,请求登陆

服务器收到请求后,向客户端返回回应消息,表示同意接受该用户加入,并把自己(指的是服务器)所在监听的端口发送给客户端

客户端根据服务器发送过来的端口号和服务器建立连接

服务器通过该连接 把在线用户的列表信息发送给新加入的客户端。

客户端获得了在线用户列表后就可以自己选择在线用户聊天。(程序中另外设计一个类似QQ的聊天窗口来进行聊天)

当用户退出系统时也要及时通知服务器,服务器再把这个消息转发给每个在线的用户,使客户端及时更新本地的用户信息列表。

2.2 通信协议设计

所谓协议就是约定,即服务器和客户端之间会话信息的内容格式进行约定,使双方都可以识别,达到更好的通信。

下面就具体介绍下协议的设计:

客户端和服务器之间的对话

(1)登陆过程

① 客户端用匿名UDP的方式向服务器发出下面的信息:

   login, username, localIPEndPoint

消息内容包括三个字段,每个字段用 “,”分割,login表示的是请求登陆;username表示用户名;localIPEndPint表示客户端本地地址。

② 服务器收到后以匿名UDP返回下面的回应:

Accept, port

其中Accept表示服务器接受请求,port表示服务器所在的端口号,服务器监听着这个端口的客户端连接

③ 连接服务器,获取用户列表

客户端从上一步获得了端口号,然后向该端口发起TCP连接,向服务器索取在线用户列表,服务器接受连接后将用户列表传输到客户端。用户列表信息格式如下:

  username1,IPEndPoint1;username2,IPEndPoint2;...;end

username1、username2表示用户名,IPEndPoint1,IPEndPoint2表示对应的端点,每个用户信息都是由"用户名+端点"组成,用户信息以“;”隔开,整个用户列表以“end”结尾。

(2)注销过程

用户退出时,向服务器发送如下消息:

   loGout,username,localIPEndPoint

这条消息看字面意思大家都知道就是告诉服务器 username+localIPEndPoint这个用户要退出了。

服务器管理用户

(1)新用户加入通知

因为系统中在线的每个用户都有一份当前在线用户表,因此当有新用户登录时,服务器不需要重复地给系统中的每个用户再发送所有用户信息,只需要将新加入用户的信息通知其他用户,其他用户再更新自己的用户列表。

服务器向系统中每个用户广播如下信息:

login,username,remoteIPEndPoint

在这个过程中服务器只是负责将收到的"login"信息转发出去。

(2)用户退出

与新用户加入一样,服务器将用户退出的消息进行广播转发:

    logout,username,remoteIPEndPoint

客户端之间聊天

用户进行聊天时,各自的客户端之间是以P2P方式进行工作的,不与服务器有直接联系,这也是P2P技术的特点。

聊天发送的消息格式如下:

 talk, longtime, selfUserName, message

其中,talk表明这是聊天内容的消息;longtime是长时间格式的当前系统时间;selfUserName为发送发的用户名;message表示消息的内容。

协议设计介绍完后,下面就进入本程序的具体实现的介绍的。

注:协议是本程序的核心,也是所有软件的核心,每个软件产品的协议都是不一样的,QQ有自己的一套协议,MSN又有另一套协议,所以使用的QQ的用户无法和用MSN的朋友进行聊天。

三、程序的实现

服务器端核心代码:

View Code     // 启动服务器           // 根据博客中协议的设计部分           // 客户端先向服务器发送登录请求,然后通过服务器返回的端口号           // 再与服务器建立连接           // 所以启动服务按钮事件中有两个套接字:一个是接收客户端信息套接字和           // 监听客户端连接套接字           private void btnStart_Click(object sender, EventArgs e)           {               // 创建接收套接字               serverIp = IPAddress.Parse(txbServerIP.Text);               serverIPEndPoint = new IPEndPoint(serverIp, int.Parse(txbServerport.Text));               receiveUdpClient = new UdpClient(serverIPEndPoint);               // 启动接收线程               Thread receiveThread = new Thread(ReceiveMessage);               receiveThread.Start();               btnStart.Enabled = false;               btnStop.Enabled = true;                  // 随机指定监听端口               Random random = new Random();               tcpPort = random.Next(port + 1, 65536);                  // 创建监听套接字               tcpListener = new TcpListener(serverIp, tcpPort);               tcpListener.Start();                  // 启动监听线程               Thread listenThread = new Thread(ListenClientConnect);               listenThread.Start();               AddItemToListBox(string.FORMat("服务器线程{0}启动,监听端口{1}",serverIPEndPoint,tcpPort));           }              // 接收客户端发来的信息           private void ReceiveMessage()           {               IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 0);               while (true)               {                   try                  {                       // 关闭receiveUdpClient时下面一行代码会产生异常                       byte[] receiveBytes = receiveUdpClient.Receive(ref remoteIPEndPoint);                       string message = Encoding.Unicode.GetString(receiveBytes, 0, receiveBytes.Length);                          // 显示消息内容                       AddItemToListBox(string.Format("{0}:{1}",remoteIPEndPoint,message));                          // 处理消息数据                       // 根据协议的设计部分,从客户端发送来的消息是具有一定格式的                       // 服务器接收消息后要对消息做处理                       string[] splitstring = message.Split(',');                       // 解析用户端地址                       string[] splitsubstring = splitstring[2].Split(':');                       IPEndPoint clientIPEndPoint = new IPEndPoint(IPAddress.Parse(splitsubstring[0]), int.Parse(splitsubstring[1]));                       switch (splitstring[0])                       {                           // 如果是登录信息,向客户端发送应答消息和广播有新用户登录消息                           case "login":                               User user = new User(splitstring[1], clientIPEndPoint);                               // 往在线的用户列表添加新成员                               userList.Add(user);                               AddItemToListBox(string.Format("用户{0}({1})加入", user.GetName(), user.GetIPEndPoint()));                               string sendString = "Accept," + tcpPort.ToString();                               // 向客户端发送应答消息                               SendtoClient(user, sendString);                               AddItemToListBox(string.Format("向{0}({1})发出:[{2}]", user.GetName(), user.GetIPEndPoint(), sendString));                               for (int i = 0; i < userList.Count; i++)                               {                                   if (userList[i].GetName() != user.GetName())                                   {                                       // 给在线的其他用户发送广播消息                                       // 通知有新用户加入                                       SendtoClient(userList[i], message);                                   }                               }                                  AddItemToListBox(string.Format("广播:[{0}]", message));                               break;                           case "logout":                               for (int i = 0; i < userList.Count; i++)                               {                                   if (userList[i].GetName() == splitstring[1])                                   {                                       AddItemToListBox(string.Format("用户{0}({1})退出",userList[i].GetName(),userList[i].GetIPEndPoint()));                                       userList.RemoveAt(i); // 移除用户                                   }                               }                               for (int i = 0; i < userList.Count; i++)                               {                                   // 广播注销消息                                   SendtoClient(userList[i], message);                               }                               AddItemToListBox(string.Format("广播:[{0}]", message));                               break;                       }                   }                   catch                  {                       // 发送异常退出循环                       break;                   }               }               AddItemToListBox(string.Format("服务线程{0}终止", serverIPEndPoint));           }              // 向客户端发送消息           private void SendtoClient(User user, string message)           {               // 匿名方式发送               sendUdpClient = new UdpClient(0);               byte[] sendBytes = Encoding.Unicode.GetBytes(message);               IPEndPoint remoteIPEndPoint =user.GetIPEndPoint();               sendUdpClient.Send(sendBytes,sendBytes.Length,remoteIPEndPoint);               sendUdpClient.Close();           }                     // 接受客户端的连接           private void ListenClientConnect()           {               TcpClient newClient = null;               while (true)               {                   try                  {                       newClient = tcpListener.AcceptTcpClient();                       AddItemToListBox(string.Format("接受客户端{0}的TCP请求",newClient.Client.RemoteEndPoint));                   }                   catch                  {                       AddItemToListBox(string.Format("监听线程({0}:{1})", serverIp, tcpPort));                       break;                   }                      Thread sendThread = new Thread(SendData);                   sendThread.Start(newClient);               }           }              // 向客户端发送在线用户列表信息           // 服务器通过TCP连接把在线用户列表信息发送给客户端           private void SendData(object userClient)           {               TcpClient newUserClient = (TcpClient)userClient;               userListstring = null;               for (int i = 0; i < userList.Count; i++)               {                   userListstring += userList[i].GetName() + ","                      + userList[i].GetIPEndPoint().ToString() + ";";               }                  userListstring += "end";               networkStream = newUserClient.GetStream();               binaryWriter = new BinaryWriter(networkStream);               binaryWriter.Write(userListstring);               binaryWriter.Flush();               AddItemToListBox(string.Format("向{0}发送[{1}]", newUserClient.Client.RemoteEndPoint, userListstring));               binaryWriter.Close();               newUserClient.Close();           }

客户端核心代码:

View Code     // 登录服务器           private void btnlogin_Click(object sender, EventArgs e)           {               // 创建接受套接字               IPAddress clientIP = IPAddress.Parse(txtLocalIP.Text);               clientIPEndPoint = new IPEndPoint(clientIP, int.Parse(txtlocalport.Text));               receiveUdpClient = new UdpClient(clientIPEndPoint);               // 启动接收线程               Thread receiveThread = new Thread(ReceiveMessage);               receiveThread.Start();                  // 匿名发送               sendUdpClient = new UdpClient(0);               // 启动发送线程               Thread sendThread = new Thread(SendMessage);               sendThread.Start(string.Format("login,{0},{1}", txtusername.Text, clientIPEndPoint));                  btnlogin.Enabled = false;               btnLogout.Enabled = true;               this.Text = txtusername.Text;           }              // 客户端接受服务器回应消息            private void ReceiveMessage()           {               IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any,0);               while (true)               {                   try                  {                       // 关闭receiveUdpClient时会产生异常                       byte[] receiveBytes = receiveUdpClient.Receive(ref remoteIPEndPoint);                       string message = Encoding.Unicode.GetString(receiveBytes,0,receiveBytes.Length);                          // 处理消息                       string[] splitstring = message.Split(',');                          switch (splitstring[0])                       {                           case "Accept":                               try                              {                                   tcpClient = new TcpClient();                                   tcpClient.Connect(remoteIPEndPoint.Address, int.Parse(splitstring[1]));                                   if (tcpClient != null)                                   {                                       // 表示连接成功                                       networkStream = tcpClient.GetStream();                                       binaryReader = new BinaryReader(networkStream);                                   }                               }                               catch                              {                                   MessageBox.Show("连接失败", "异常");                               }                                  Thread getUserListThread = new Thread(GetUserList);                               getUserListThread.Start();                               break;                           case "login":                               string userItem = splitstring[1] + "," + splitstring[2];                               AddItemToListView(userItem);                               break;                           case "logout":                               RemoveItemFromListView(splitstring[1]);                               break;                           case "talk":                               for (int i = 0; i < chatFormList.Count; i++)                               {                                   if (chatFormList[i].Text == splitstring[2])                                   {                                       chatFormList[i].ShowTalkInfo(splitstring[2], splitstring[1], splitstring[3]);                                   }                               }                                  break;                       }                   }                   catch                  {                       break;                   }               }           }              // 从服务器获取在线用户列表           private void GetUserList()           {               while (true)               {                   userListstring = null;                   try                  {                       userListstring = binaryReader.ReadString();                       if (userListstring.EndsWith("end"))                       {                           string[] splitstring = userListstring.Split(';');                           for (int i = 0; i < splitstring.Length - 1; i++)                           {                               AddItemToListView(splitstring[i]);                           }                              binaryReader.Close();                           tcpClient.Close();                           break;                       }                   }                   catch                  {                       break;                   }               }           }      // 发送登录请求           private void SendMessage(object obj)           {               string message = (string)obj;               byte[] sendbytes = Encoding.Unicode.GetBytes(message);               IPAddress remoteIp = IPAddress.Parse(txtserverIP.Text);               IPEndPoint remoteIPEndPoint = new IPEndPoint(remoteIp, int.Parse(txtServerport.Text));               sendUdpClient.Send(sendbytes, sendbytes.Length, remoteIPEndPoint);               sendUdpClient.Close();           }

程序的运行结果:

首先先运行服务器窗口,在服务器窗口点击“启动”按钮来启动服务器,然后客户端首先指定服务器的端口号,修改用户名(这里也可以不修改,使用默认的也可以),然后点击“登录”按钮来登陆服务器(也就是告诉服务器本地的客户端地址),然后从服务器端获得在线用户列表,界面演示如下:

C#的即时通信程序怎么实现

然后用户可以双击在线用户进行聊天(此程序支持与多人进行聊天),下面是功能的演示图片:

C#的即时通信程序怎么实现

双方进行聊天时,这里没有实现像QQ一样,有人发信息来在对应的客户端就有消息提醒的功能的, 所以双方进行聊天的过程中,每个客户端都需要在在线用户列表中点击聊天的对象来激活聊天对话框(意思就是从图片中可以看出“天涯”客户端想和剑痴聊天的话,就在“在线用户”列表双击剑痴来激活聊天窗口,同时“剑痴”客户端也必须双击“天涯”来激活聊天窗口,这样双方就看到对方发来的信息了,(不激活窗口,也是发送了信息,只是没有一个窗口来进行显示)),而且从图片中也可以看出&mdash;&mdash;此程序支持与多人聊天,即天涯同时与“剑痴”和"大地"同时聊天。

到此,关于“C#的即时通信程序怎么实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: C#的即时通信程序怎么实现

本文链接: https://www.lsjlt.com/news/288110.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#的即时通信程序怎么实现
    这篇文章主要介绍“C#的即时通信程序怎么实现”,在日常操作中,相信很多人在C#的即时通信程序怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#的即时通信程序怎么实现”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-17
  • C++如何实现即时通信
    本篇内容主要讲解“C++如何实现即时通信”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++如何实现即时通信”吧!软件:VS服务器端//TcpServer_plus.exe#include<...
    99+
    2023-06-30
  • python内网即时通信小程序
    环境:kali 一个server.py和client.pysever.py# -*- coding: utf-8 -* #Server.py import socket host = socket.gethostname() port =...
    99+
    2023-01-31
    内网 即时通信 程序
  • 微信小程序如何使用WebSocket实现即时通讯
    使用WebSocket实现即时通讯功能,可以让用户实时收发消息,并保持连接状态。在微信小程序中,可以通过wx.connectSock...
    99+
    2024-04-03
    微信小程序 WebSocket
  • C++实现即时通信的示例代码(直接运行)
    目录题目软件:VS服务器端客户端题目 由于本学期上了网络编程课程,老师要求写使用Socke实现网络编程。于是参考 C++多线程实现即时通信软件 写出了简单版本的没有界面的即时通信软件...
    99+
    2024-04-02
  • SpringBoot怎么实现WebSocket即时通讯
    这篇“SpringBoot怎么实现WebSocket即时通讯”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoo...
    99+
    2023-06-30
  • php 怎么实现即时通讯实例
    本教程操作环境:windows7系统、PHP8.1版、Dell G3电脑。php 怎么实现即时通讯实例?仿百度商桥IM即时通讯(Laravel)基于workerman和websocket开发实时聊天系统仿百度商桥IM通讯实现原理及方法:1、...
    99+
    2024-04-02
  • 小程序中如何实现即时通讯功能
    在小程序中实现即时通讯功能通常需要使用到实时通讯的服务接口和技术。下面是一个简单的步骤来实现即时通讯功能: 选择合适的即时通讯服...
    99+
    2024-04-17
    小程序
  • java实现实时通信聊天程序
    利用TCP传输数据,编写客户端和服务器的程序,实现两个程序间的实时通信。 在每个程序中实现了实时的发送与接收数据的功能。 客户端的io界面 服务器端的io界面 io演示 程序以...
    99+
    2024-04-02
  • VB.NET怎么实现通信程序
    这篇文章主要介绍VB.NET怎么实现通信程序,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1992年crescent software inc.公司专为vb设计mscomm.vbx用户通信控件。VB.NET通信程序提...
    99+
    2023-06-17
  • SpringBoot整合websocket实现即时通信聊天
    目录一、技术介绍1.1 客户端WebSocket1.1.1 函数1.1.2 事件1.2 服务端WebSocket二、实战 2.1、服务端2.1.1引入maven依赖2.1....
    99+
    2024-04-02
  • PHP和WebSocket: 实现即时通信的优化方法
    PHP和WebSocket: 实现即时通信的优化方法引言:随着互联网的快速发展,即时通信成为人们生活中必不可少的一部分。而在建立一个高效和可靠的即时通信系统中,WebSocket技术的应用变得越来越普遍,它可以实现双向实时通信,大大提高了用...
    99+
    2023-12-17
    优化 PHP websocket
  • 如何利用微信小程序和php实现即时通讯聊天功能
    目录一、PHP7安装Swoole扩展1、自定义安装2、宝塔面板安装PHP swoole扩展二、配置nginx反向代理三、微信小程序socket合法域名配置四、效果演示和代码1、小程序...
    99+
    2024-04-02
  • golang WebSocket与浏览器的集成:实现即时通信
    Golang是一种高效、简单、易于学习的编程语言,而WebSocket是实现即时通信的重要技术。本文将介绍如何在Golang中集成WebSocket,并实现与浏览器的即时通信功能。1. 引言在Web应用开发中,实时通信是一种非常重要的功能要...
    99+
    2023-12-17
    Golang websocket 即时通信
  • 微信小程序中怎么使用GoEasy实现实时通讯
    本篇文章给大家分享的是有关微信小程序中怎么使用GoEasy实现实时通讯,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1、获取appkeyGoE...
    99+
    2024-04-02
  • AndroidSocket实现多个客户端即时通信聊天
    聊天室的原理是这样的,一个客户端与服务器建立通讯成功,即客户端socket连接到服务器的ServerSocket之后,服务器端程序将对应的socket加入到容器中,为每一个socke...
    99+
    2024-04-02
  • socket.io怎么即时通信前端配合Node
    小编给大家分享一下socket.io怎么即时通信前端配合Node,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!首先我们需要 新建文件夹 并快速生成一个packag...
    99+
    2023-06-14
  • PHP和WebSocket: 实现即时通信的完美解决方案
    随着互联网的快速发展,越来越多的应用需要实现即时通信功能,比如在线聊天、实时数据监控等。而传统的 HTTP 协议并不适合这种场景,因为它是基于请求/响应的,必须客户端不断向服务器发送请求才能获取最新数据,这样带来了很大的开销和延迟。为了解决...
    99+
    2023-12-17
    PHP websocket 即时通信
  • PHP和WebSocket: 实现即时通信的完美解决方案
    随着互联网的快速发展,越来越多的应用需要实现即时通信功能,比如在线聊天、实时数据监控等。而传统的 HTTP 协议并不适合这种场景,因为它是基于请求/响应的,必须客户端不断向服务器发送请求才能获取最新数据,这样带来了很大的开销和延迟。为了解决...
    99+
    2023-12-17
    PHP websocket 即时通信
  • C#怎么实现Socket通信
    这篇文章给大家分享的是有关C#怎么实现Socket通信的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码如下: //创建socket对象     &nb...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作