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

功能
我们首先需要知道我们和对方的网络地址,现在主流的ip地址是IPV4和IPV6。
之后我们就可以通过这些地址进行双向通信,实现聊天室的功能。
实现
查看本机IP
打开windows的控制面板(按win +R )
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjI5MTA5,size_16,color_FFFFFF,t_70#pic_center.jpg
输入cmd
输入ipconfig查看本机IP
20210604105632817.jpg
发送端
        //获取当前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();
  •         }
  • 复制代码
    接收端
    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();
  •         }
  •     }
  • }
  • 复制代码
    使用流程

    • 在发送端程序中输入IP地址
    • 运行发送端程序,在输入框中输入要发送的消息
    • 运行接收端信息
    • 输入IP地址
    • 查看消息框
    运行结果

    watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0NjI5MTA5,size_16,color_FFFFFF,t_70#pic_center.jpg
    程序