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
原文地址:https://www.cnblogs.com/LiuZhen/p/3503749.html