• Udp通讯(零基础)


    前面学习了Tcp通讯之后听老师同学们讲到Udp也可以通讯,实现还要跟简单,没有繁琐的连接,所以最近学习了一下,记录下来以便忘记,同时也发表出来与大家相互学习,下面是我自己写的一个聊天例子,实现了群聊私聊等功能。

    通讯类(UdpInfo)

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace Model
     8 {
     9     [Serializable]
    10     public class UdpInfo
    11     {
    12         public string Name { get; set; }
    13         public string Ip { get; set; }
    14         public string Port { get; set; }
    15         public string Message { get; set; }
    16         public int Types { get; set; }//消息的类型
    17         public bool IsFist { get; set; }//判断加载的成员是否是第一个
    18         public string ToName { get; set; }//与谁私聊
    19         public string LoginName { get; set; }//新加入成员的名字
    20     }
    21 }
    View Code

    服务器(Server)

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Threading.Tasks;
      9 using System.Windows.Forms;
     10 using System.Net;
     11 using System.Net.Sockets;
     12 using System.Threading;
     13 using System.IO;
     14 using System.Runtime.Serialization.Formatters.Binary;
     15 using Model;
     16 
     17 namespace Server
     18 {
     19     public partial class forUdp : Form
     20     {
     21         public forUdp()
     22         {
     23             InitializeComponent();
     24         }
     25         UdpClient server = null;
     26         IPEndPoint ipEndPoint = null;
     27         List<IPEndPoint> pointList = new List<IPEndPoint>();//成员集合
     28         private delegate void BindDelegate(UdpInfo u);//(绑定信息)
     29         BindDelegate bd = null;
     30         private bool flag;//是否为添加的第一个成员
     31         private string loginName;
     32         private void Form1_Load(object sender, EventArgs e)
     33         {
     34             txtPort.Text = "9018";//默认的端口
     35         }
     36         public void Receices()//接收客户端的消息
     37         {
     38             while (true)
     39             {
     40                 try
     41                 {
     42                     byte[] bytes = server.Receive(ref ipEndPoint);//获取消息
     43                     UdpInfo u = DeserializeObject(bytes) as UdpInfo;
     44                     bd = new BindDelegate(BindRtb);
     45                     this.Invoke(bd, u);
     46                 }
     47                 catch (Exception)
     48                 {
     49                     server.Close();//有异常关闭服务
     50                 }
     51             }
     52         }
     53         public object DeserializeObject(byte[] pBytes)//反序列化二进制为对象
     54         {
     55             object newOjb = null;
     56             if (pBytes == null)
     57                 return newOjb;
     58             MemoryStream memory = new MemoryStream(pBytes);
     59             memory.Position = 0;
     60             BinaryFormatter formatter = new BinaryFormatter();
     61             newOjb = formatter.Deserialize(memory);
     62             memory.Close();
     63             return newOjb;
     64         }
     65         public byte[] SerializeObject(object pObj)//序列化对象为二进制的数
     66         {
     67             if (pObj == null)
     68                 return null;
     69             MemoryStream memory = new MemoryStream();
     70             BinaryFormatter formatter = new BinaryFormatter();
     71             formatter.Serialize(memory, pObj);
     72             memory.Position = 0;
     73             byte[] read = new byte[memory.Length];
     74             memory.Read(read, 0, read.Length);
     75             memory.Close();
     76             return read;
     77         }
     78         public void BindRtb(UdpInfo u) //添加信息,绑定信息
     79         {
     80             if(u.Types == 0)//如果消息类型为上线
     81             {
     82                 pointList.Add(ipEndPoint);//添加成员
     83                 //u.Name = "1";
     84                 //获取需要的基本信息
     85                 loginName = u.Name;
     86                 u.Ip = ipEndPoint.ToString().Split(':')[0];
     87                 u.Port = ipEndPoint.ToString().Split(':')[1];
     88                 byte[] bytes = SerializeObject(u);
     89                 ListViewItem item = new ListViewItem(u.Name);//绑定添加到成员列表上
     90                 item.SubItems.Add(u.Ip);
     91                 item.SubItems.Add(u.Port);
     92                 lvInfo.Items.Add(item);//显示成员信息
     93                 BindListView(loginName);//成员发生改变的时候,发送成员信息给客户端,刷新客户端的成员信息
     94             }
     95             else if (u.Types == 1)//如果消息的类型是群聊的话就执行
     96             {
     97                 foreach (ListViewItem items in lvInfo.Items)//循环每个成员
     98                 {
     99                     IPAddress ip = IPAddress.Parse(items.SubItems[1].Text);
    100                     IPEndPoint ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[2].Text));
    101                     byte[] bytes = SerializeObject(u);
    102                     server.Send(bytes, bytes.Length, ipEndPoint);//给每个用户发送信息
    103                 }
    104             }
    105             else if (u.Types == 2)//消息的类型是私聊
    106             {
    107                 foreach(ListViewItem items in lvInfo.Items)
    108                 {
    109                     //如果该成员是指定成员才发送信息
    110                     if(u.ToName.Equals(items.SubItems[0].Text))
    111                     {
    112                         IPAddress ip = IPAddress.Parse(items.SubItems[1].Text);
    113                         IPEndPoint ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[2].Text));
    114                         byte[] bytes = SerializeObject(u);
    115                         server.Send(bytes, bytes.Length, ipEndPoint);//发送消息给指定的用户
    116                     }
    117                 }
    118             }
    119             else if(u.Types == 3)//如果消息的类型是下线的话
    120             {
    121                 IPEndPoint ipEndPoint = null;
    122                 foreach (ListViewItem items in lvInfo.Items)//循环每个成员
    123                 {
    124                     IPAddress ip = IPAddress.Parse(items.SubItems[1].Text);
    125                     ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[2].Text));
    126                     if(items.SubItems[0].Text.Equals(u.Name))
    127                     {
    128                         lvInfo.Items.Remove(items);//从ListView集合中移除  
    129                         pointList.Remove(ipEndPoint);//从List<IPEndPoint>集合中移除
    130                         continue;
    131                     }
    132                     byte[] bytes = SerializeObject(u);
    133                     server.Send(bytes, bytes.Length, ipEndPoint);//给每个用户发送信息
    134                 }
    135             }
    136             //服务器接收所有的消息
    137             rtbMessage.Text += "
    " + u.Name + ":" + u.Message;
    138         }
    139         public void BindListView(string loginName) //有新成员加入的时候就绑定刷新成员列表
    140         {
    141             flag = true;
    142             foreach (ListViewItem items in lvInfo.Items)//循环每个用户
    143             {
    144                 foreach (ListViewItem item in lvInfo.Items)//给每个用户发送全部的成员信息
    145                 {
    146                     UdpInfo u = new UdpInfo();
    147                     u.Name = item.SubItems[0].Text.ToString();
    148                     u.IsFist = flag;//添加第一个成员的时候因为要重新初始化客户端成员列表,而剩下的则不要初始化,所以要设置为true
    149                     flag = false;
    150                     u.LoginName = loginName;
    151                     u.Message = "上线了!";
    152                     u.Ip = item.SubItems[1].Text.ToString();
    153                     u.Port = item.SubItems[2].Text.ToString();
    154                     byte[] bytes = SerializeObject(u);
    155                     IPAddress ip = IPAddress.Parse(items.SubItems[1].Text);
    156                     IPEndPoint ipp = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[2].Text));//得到成员的IPEndPoint
    157                     server.Send(bytes, bytes.Length, ipp);
    158                 }
    159             }
    160         }
    161         private void 结束程序ToolStripMenuItem_Click(object sender, EventArgs e)
    162         {
    163             server.Close();
    164             this.Dispose();
    165             Application.Exit();
    166         }
    167 
    168         private void 运行程序ToolStripMenuItem_Click(object sender, EventArgs e)
    169         {
    170             rtbMessage.Text = "可以发送消息过来了!";
    171             int port = Convert.ToInt32(txtPort.Text);
    172             server = new UdpClient(port);
    173             ipEndPoint = new IPEndPoint(IPAddress.Any, port);
    174             Thread t = new Thread(new ThreadStart(Receices));
    175             t.Start();
    176         }
    177     }
    178 }
    View Code

    客户端(Client)

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Threading.Tasks;
      9 using System.Windows.Forms;
     10 using System.Net;
     11 using System.Net.Sockets;
     12 using System.Threading;
     13 using Model;
     14 using System.IO;
     15 using System.Runtime.Serialization.Formatters.Binary;
     16 
     17 namespace Client
     18 {
     19     public partial class forUdp : Form
     20     {
     21         public forUdp()
     22         {
     23             InitializeComponent();
     24         }
     25         UdpClient client = null;
     26         IPEndPoint ipEndPoints = null;
     27         private delegate void BindDelegate(UdpInfo u);
     28         BindDelegate bd = null;
     29         private void forUdp_Load(object sender, EventArgs e)
     30         {
     31             txtIP.Text = "192.168.1.109";
     32             txtPort.Text = "9018";
     33             txtName.Text = "小哈";
     34         }
     35 
     36         private void 运行程序ToolStripMenuItem_Click(object sender, EventArgs e)
     37         {
     38             rtbMessage.Text = "可以发送消息过去了!";
     39             int port = Convert.ToInt32(txtPort.Text);
     40             ipEndPoints = new IPEndPoint(IPAddress.Parse(txtIP.Text), port);
     41             client = new UdpClient();
     42             client.Connect(IPAddress.Parse(txtIP.Text), port);//关联此IP和端口
     43             Send(new UdpInfo() {Name = txtName.Text,Message = "上线了!", Types = 0 });
     44             Thread t = new Thread(new ThreadStart(Receices));
     45             t.Start();
     46         }
     47 
     48         public void Receices()//接收客户端的消息
     49         {
     50             while (true)
     51             {
     52                 try
     53                 {
     54                     byte[] bytes = client.Receive(ref ipEndPoints);
     55                     UdpInfo u = DeserializeObject(bytes) as UdpInfo;
     56                     bd = new BindDelegate(BindRtb);
     57                     this.Invoke(bd, u);
     58                 }
     59                 catch (Exception)
     60                 {
     61                     client.Close();
     62                 }
     63             }
     64         }
     65         public object DeserializeObject(byte[] pBytes)//反序列化二进制为对象
     66         {
     67             object newOjb = null;
     68             if (pBytes == null)
     69                 return newOjb;
     70             MemoryStream memory = new MemoryStream(pBytes);
     71             memory.Position = 0;
     72             BinaryFormatter formatter = new BinaryFormatter();
     73             newOjb = formatter.Deserialize(memory);
     74             memory.Close();
     75             return newOjb;
     76         }
     77         public byte[] SerializeObject(object pObj)//序列化对象为二进制的数
     78         {
     79             if (pObj == null)
     80                 return null;
     81             MemoryStream memory = new MemoryStream();
     82             BinaryFormatter formatter = new BinaryFormatter();
     83             formatter.Serialize(memory, pObj);
     84             memory.Position = 0;
     85             byte[] read = new byte[memory.Length];
     86             memory.Read(read, 0, read.Length);
     87             memory.Close();
     88             return read;
     89         }
     90         public void BindRtb(UdpInfo u)//将消息添加到消息框中
     91         {
     92             if (u.Types == 0)
     93             {
     94                 if (u.IsFist == true)
     95                     lvInfo.Items.Clear();
     96                 ListViewItem item = new ListViewItem(u.Name);
     97                 item.SubItems.Add(u.Ip);
     98                 item.SubItems.Add(u.Port);
     99                 lvInfo.Items.Add(item);
    100             }
    101             else if (u.Types == 3)//如果消息的类型是下线的话
    102             {
    103                 IPEndPoint ipEndPoint = null;
    104                 foreach (ListViewItem items in lvInfo.Items)//循环每个成员
    105                 {
    106                     if (items.SubItems[0].Text.Equals(u.Name))
    107                     {
    108                         IPAddress ip = IPAddress.Parse(items.SubItems[1].Text);
    109                         ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[2].Text));
    110                         lvInfo.Items.Remove(items);//从ListView集合中移除  
    111                         continue;
    112                     }
    113                 }
    114             }
    115             foreach (ListViewItem items in lvInfo.Items)
    116             {
    117                 if(items.SubItems[0].Text.Equals(u.LoginName))
    118                     rtbMessage.Text += "
    " + u.Name + ":" + u.Message;
    119             }
    120         }
    121         public void Send(UdpInfo u)//发送消息给服务器
    122         {
    123             byte[] bytes = SerializeObject(u);     
    124             client.Send(bytes, bytes.Length);
    125         }
    126         private void 结束程序ToolStripMenuItem_Click(object sender, EventArgs e)
    127         {
    128             Send(new UdpInfo() { Name = txtName.Text, Message = "下线了!", Types = 3 });
    129             client.Close(); 
    130             Application.Exit();
    131         }
    132 
    133         private void btnSend_Click(object sender, EventArgs e)
    134         {
    135             UdpInfo u = new UdpInfo() { 
    136                 Name = txtName.Text, Message = rtbNews.Text, Types = 1
    137             };
    138             if (lvInfo.SelectedItems.Count > 0)//如果有选中的成员的话
    139             {
    140                 u.Types = 2;
    141                 u.ToName = lvInfo.SelectedItems[0].SubItems[0].Text;
    142             }
    143             Send(u);
    144             lvInfo.SelectedItems.Clear();//清除上一次的痕迹
    145         }
    146     }
    147 }
    View Code
  • 相关阅读:
    对于CD翻录的一些记录
    暑期实践
    暑期实践
    垃圾处理器-CMS
    离合器半联动点的判断和技巧
    Win10+VS2019+OpenCV环境配置
    C++ 学习资料
    科目二起步原理
    道路交通安全违法行为记分分值分类总结
    NWERC 2020 题解
  • 原文地址:https://www.cnblogs.com/LiuZhen/p/3503749.html
Copyright © 2020-2023  润新知