前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微信、QQ聊天是怎么实现的?原来这么简单!!!

微信、QQ聊天是怎么实现的?原来这么简单!!!

原创
作者头像
跋扈洋
修改2021-06-04 14:20:03
3.8K0
修改2021-06-04 14:20:03
举报
文章被收录于专栏:物联网知识

需求

相信我们所有人都使用过或正在使用扣扣和微信。QQ是一款基于互联网的即时通信软件。我们在享受即时通讯的便捷和智能时,是否也想过,QQ、微信的聊天功能是怎么实现的?

功能

我们首先需要知道我们和对方的网络地址,现在主流的ip地址是IPV4和IPV6。 之后我们就可以通过这些地址进行双向通信,实现聊天室的功能。

实现

查看本机IP

  1. 打开windows的控制面板(按win +R )
  2. 输入cmd
  1. 输入ipconfig查看本机IP
1
1

发送端

本位置的程序主要为了让大家理解是怎么制作发送端的程序。具体完整的项目工程文件在下方会有所有的程序供大家下载。

代码语言:javascript
复制
        //获取当前IPv4地址
        private string GetIpAddress()
        {
            string hostName = Dns.GetHostName();   //获取本机名
            IPHostEntry localhost = Dns.GetHostByName(hostName);    //方法已过期,可以获取IPv4的地址
                                                                    //IPHostEntry localhost = Dns.GetHostEntry(hostName);   //获取IPv6地址
            IPAddress localaddr = localhost.AddressList[0];

            return localaddr.ToString();
        }
        public void UdpSend()
        {
            //Parse()把十进制iP转化成IPAddress类,绑定IP地址和端口
            remoteIPEp = new IPEndPoint(IPAddress.Parse("IP地址"), CLIENT_UDP_PORT);
            //创建发送数据 Socket 对象与数据缓冲区
            udpSendDataBuf = new byte[1024];
            skUdpSend = new Socket(AddressFamily.InterNetwork,
            SocketType.Dgram, ProtocolType.Udp);
            //为false,等待执行
            mreUdpShutDown = new ManualResetEvent(false);
            mreUdpSend = new ManualResetEvent(false);
            whUdp = new WaitHandle[2];
            whUdp[0] = mreUdpShutDown;//UDP结束命令
            whUdp[1] = mreUdpSend; //UDP服务结束命令
            int iWaitRetCode;
            iWaitRetCode = WaitHandle.WaitAny(whUdp, 1000);   //等待指定数组中的任意元素接收信号,同时使用 TimeSpan 指定时间间隔
            byte[] b_txt;
            int iByteLen;

            //满足条件
            while (iWaitRetCode != 0)
            {
                switch (iWaitRetCode)
                {
                    case 1://发送数据 
                        b_txt = Encoding.UTF8.GetBytes(strSendTxt);
                        iByteLen = b_txt.Length;
                        //初始化缓存数据
                        Array.Clear(udpSendDataBuf, iWaitRetCode, iByteLen);
                        //复制数组
                        Array.Copy(b_txt, udpSendDataBuf, iByteLen);
                        //发送到指定IP
                        skUdpSend.SendTo(udpSendDataBuf, remoteIPEp);
                        //消费掉一次事件
                        mreUdpSend.Reset();
                        break;
                    case WaitHandle.WaitTimeout://超时
                        break;
                }
                //继续下次事件检测
                iWaitRetCode = WaitHandle.WaitAny(whUdp, 1000);
            }
            skUdpSend.Close();
            skUdpSend = null;
        }
        #endregion    UDP发送线程线程 
        public static string strSendTxt;
        private void button1_Click(object sender, EventArgs e)
        {
            mreUdpShutDown.Set();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            strSendTxt = GetIpAddress() +":"+ textBox1.Text + "\r\n";
            mreUdpSend.Set();
        }

        private void liaotian_Load(object sender, EventArgs e)
        {
            //线程开始
            ThreadStart theStart = new ThreadStart(UdpSend);
            Thread theThr = new Thread(theStart);
            theThr.Start();
        }

        private void liaotian_FormClosing(object sender, FormClosingEventArgs e)
        {
            mreUdpShutDown.Set();
        }

接收端

本位置的程序主要为了让大家理解是怎么制作发送端的程序。具体完整的项目工程文件在下方会有所有的程序供大家下载。

代码语言:javascript
复制
namespace FormUdpSend
{
    public partial class send : Form
    {
        public send()
        {
            InitializeComponent();
        }
        #region  UDP发送线程
        public static int iUdpRecvPkgLen;
        public static Socket skUdpSend;
        public static byte[] udpSendDataBuf;
        public static IPEndPoint remoteIPEp;  //IP地址和端口的绑定
        public static int CLIENT_UDP_PORT = 0x5555;  //分配给 Port属性,例子用ipv4

        public static ManualResetEvent mreUdpShutDown;//UDP结束命令
        public static ManualResetEvent mreUdpSend;//UDP发送命令
        public static WaitHandle[] whUdp;  //UDP相关句柄
        //获取当前IPv4地址
        private string GetIpAddress()
        {
            string hostName = Dns.GetHostName();   //获取本机名
            IPHostEntry localhost = Dns.GetHostByName(hostName);    //方法已过期,可以获取IPv4的地址
                                                                    //IPHostEntry localhost = Dns.GetHostEntry(hostName);   //获取IPv6地址
            IPAddress localaddr = localhost.AddressList[0];

            return localaddr.ToString();
        }

        public void UdpSend()
        {
            //Parse()把十进制iP转化成IPAddress类,绑定IP地址和端口
            remoteIPEp = new IPEndPoint(IPAddress.Parse("169.254.7.216"), CLIENT_UDP_PORT);
            //创建发送数据 Socket 对象与数据缓冲区
            udpSendDataBuf = new byte[1024];
            skUdpSend = new Socket(AddressFamily.InterNetwork,
            SocketType.Dgram, ProtocolType.Udp);

            //为false,等待执行
            mreUdpShutDown = new ManualResetEvent(false);
            mreUdpSend = new ManualResetEvent(false);
            whUdp = new WaitHandle[2];
            whUdp[0] = mreUdpShutDown;//UDP结束命令
            whUdp[1] = mreUdpSend; //UDP服务结束命令 

            int iWaitRetCode;
            iWaitRetCode = WaitHandle.WaitAny(whUdp, 1000);   //等待指定数组中的任意元素接收信号,同时使用 TimeSpan 指定时间间隔
            byte[] b_txt;
            int iByteLen;

            //满足条件
            while (iWaitRetCode != 0)
            {
                switch (iWaitRetCode)
                {
                    case 1://发送数据 
                        b_txt = Encoding.UTF8.GetBytes(strSendTxt);
                        iByteLen = b_txt.Length;
                        //初始化缓存数据
                        Array.Clear(udpSendDataBuf, iWaitRetCode, iByteLen);
                        //复制数组
                        Array.Copy(b_txt, udpSendDataBuf, iByteLen);
                        //发送到指定IP
                        skUdpSend.SendTo(udpSendDataBuf, remoteIPEp);
                        //消费掉一次事件
                        mreUdpSend.Reset();
                        break;
                    case WaitHandle.WaitTimeout://超时
                        break;
                }
                //继续下次事件检测
                iWaitRetCode = WaitHandle.WaitAny(whUdp, 1000);
            }
            skUdpSend.Close();
            skUdpSend = null;
        }
        #endregion    UDP发送线程线程 
        public static string strSendTxt;
        private void button1_Click(object sender, EventArgs e)
        {
            mreUdpShutDown.Set();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            strSendTxt = GetIpAddress() +":"+ textBox1.Text + "\r\n";
            mreUdpSend.Set();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //线程开始
            ThreadStart theStart = new ThreadStart(UdpSend);
            Thread theThr = new Thread(theStart);
            theThr.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            mreUdpShutDown.Set();
        }
    }
}

使用流程

  1. 在发送端程序中输入IP地址
  2. 运行发送端程序,在输入框中输入要发送的消息
  3. 运行接收端信息
  4. 输入IP地址
  5. 查看消息框

运行结果

程序

后续

如果想了解更多物联网、智能家居项目知识,可以关注我的公众号。

编写不易,感谢支持。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求
  • 功能
  • 实现
    • 查看本机IP
      • 发送端
        • 接收端
        • 使用流程
        • 运行结果
        • 后续
        相关产品与服务
        即时通信 IM
        即时通信 IM(Instant Messaging)基于腾讯二十余年的 IM 技术积累,支持 Android、iOS、Mac、Windows、Web、H5、小程序平台且跨终端互通,低代码 UI 组件助您30分钟集成单聊、群聊、好友与资料、消息漫游、群组管理、会话管理、直播弹幕、内容审核和推送等能力。适用于直播互动、电商带货、客服咨询、社交沟通、企业办公、互动游戏、医疗健康等场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档