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

通讯类(UdpInfo)

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Model
{
[Serializable]
public class UdpInfo
{
public string Name { get; set; }
public string Ip { get; set; }
public string Port { get; set; }
public string Message { get; set; }
public int Types { get; set; }//消息的类型
public bool IsFist { get; set; }//判断加载的成员是否是第一个
public string ToName { get; set; }//与谁私聊
public string LoginName { get; set; }//新加入成员的名字
}
}

服务器(Server)

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Model; namespace Server
{
public partial class forUdp : Form
{
public forUdp()
{
InitializeComponent();
}
UdpClient server = null;
IPEndPoint ipEndPoint = null;
List<IPEndPoint> pointList = new List<IPEndPoint>();//成员集合
private delegate void BindDelegate(UdpInfo u);//(绑定信息)
BindDelegate bd = null;
private bool flag;//是否为添加的第一个成员
private string loginName;
private void Form1_Load(object sender, EventArgs e)
{
txtPort.Text = "";//默认的端口
}
public void Receices()//接收客户端的消息
{
while (true)
{
try
{
byte[] bytes = server.Receive(ref ipEndPoint);//获取消息
UdpInfo u = DeserializeObject(bytes) as UdpInfo;
bd = new BindDelegate(BindRtb);
this.Invoke(bd, u);
}
catch (Exception)
{
server.Close();//有异常关闭服务
}
}
}
public object DeserializeObject(byte[] pBytes)//反序列化二进制为对象
{
object newOjb = null;
if (pBytes == null)
return newOjb;
MemoryStream memory = new MemoryStream(pBytes);
memory.Position = ;
BinaryFormatter formatter = new BinaryFormatter();
newOjb = formatter.Deserialize(memory);
memory.Close();
return newOjb;
}
public byte[] SerializeObject(object pObj)//序列化对象为二进制的数
{
if (pObj == null)
return null;
MemoryStream memory = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memory, pObj);
memory.Position = ;
byte[] read = new byte[memory.Length];
memory.Read(read, , read.Length);
memory.Close();
return read;
}
public void BindRtb(UdpInfo u) //添加信息,绑定信息
{
if(u.Types == )//如果消息类型为上线
{
pointList.Add(ipEndPoint);//添加成员
//u.Name = "1";
//获取需要的基本信息
loginName = u.Name;
u.Ip = ipEndPoint.ToString().Split(':')[];
u.Port = ipEndPoint.ToString().Split(':')[];
byte[] bytes = SerializeObject(u);
ListViewItem item = new ListViewItem(u.Name);//绑定添加到成员列表上
item.SubItems.Add(u.Ip);
item.SubItems.Add(u.Port);
lvInfo.Items.Add(item);//显示成员信息
BindListView(loginName);//成员发生改变的时候,发送成员信息给客户端,刷新客户端的成员信息
}
else if (u.Types == )//如果消息的类型是群聊的话就执行
{
foreach (ListViewItem items in lvInfo.Items)//循环每个成员
{
IPAddress ip = IPAddress.Parse(items.SubItems[].Text);
IPEndPoint ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[].Text));
byte[] bytes = SerializeObject(u);
server.Send(bytes, bytes.Length, ipEndPoint);//给每个用户发送信息
}
}
else if (u.Types == )//消息的类型是私聊
{
foreach(ListViewItem items in lvInfo.Items)
{
//如果该成员是指定成员才发送信息
if(u.ToName.Equals(items.SubItems[].Text))
{
IPAddress ip = IPAddress.Parse(items.SubItems[].Text);
IPEndPoint ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[].Text));
byte[] bytes = SerializeObject(u);
server.Send(bytes, bytes.Length, ipEndPoint);//发送消息给指定的用户
}
}
}
else if(u.Types == )//如果消息的类型是下线的话
{
IPEndPoint ipEndPoint = null;
foreach (ListViewItem items in lvInfo.Items)//循环每个成员
{
IPAddress ip = IPAddress.Parse(items.SubItems[].Text);
ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[].Text));
if(items.SubItems[].Text.Equals(u.Name))
{
lvInfo.Items.Remove(items);//从ListView集合中移除
pointList.Remove(ipEndPoint);//从List<IPEndPoint>集合中移除
continue;
}
byte[] bytes = SerializeObject(u);
server.Send(bytes, bytes.Length, ipEndPoint);//给每个用户发送信息
}
}
//服务器接收所有的消息
rtbMessage.Text += "\n" + u.Name + ":" + u.Message;
}
public void BindListView(string loginName) //有新成员加入的时候就绑定刷新成员列表
{
flag = true;
foreach (ListViewItem items in lvInfo.Items)//循环每个用户
{
foreach (ListViewItem item in lvInfo.Items)//给每个用户发送全部的成员信息
{
UdpInfo u = new UdpInfo();
u.Name = item.SubItems[].Text.ToString();
u.IsFist = flag;//添加第一个成员的时候因为要重新初始化客户端成员列表,而剩下的则不要初始化,所以要设置为true
flag = false;
u.LoginName = loginName;
u.Message = "上线了!";
u.Ip = item.SubItems[].Text.ToString();
u.Port = item.SubItems[].Text.ToString();
byte[] bytes = SerializeObject(u);
IPAddress ip = IPAddress.Parse(items.SubItems[].Text);
IPEndPoint ipp = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[].Text));//得到成员的IPEndPoint
server.Send(bytes, bytes.Length, ipp);
}
}
}
private void 结束程序ToolStripMenuItem_Click(object sender, EventArgs e)
{
server.Close();
this.Dispose();
Application.Exit();
} private void 运行程序ToolStripMenuItem_Click(object sender, EventArgs e)
{
rtbMessage.Text = "可以发送消息过来了!";
int port = Convert.ToInt32(txtPort.Text);
server = new UdpClient(port);
ipEndPoint = new IPEndPoint(IPAddress.Any, port);
Thread t = new Thread(new ThreadStart(Receices));
t.Start();
}
}
}

客户端(Client)

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Model;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary; namespace Client
{
public partial class forUdp : Form
{
public forUdp()
{
InitializeComponent();
}
UdpClient client = null;
IPEndPoint ipEndPoints = null;
private delegate void BindDelegate(UdpInfo u);
BindDelegate bd = null;
private void forUdp_Load(object sender, EventArgs e)
{
txtIP.Text = "192.168.1.109";
txtPort.Text = "";
txtName.Text = "小哈";
} private void 运行程序ToolStripMenuItem_Click(object sender, EventArgs e)
{
rtbMessage.Text = "可以发送消息过去了!";
int port = Convert.ToInt32(txtPort.Text);
ipEndPoints = new IPEndPoint(IPAddress.Parse(txtIP.Text), port);
client = new UdpClient();
client.Connect(IPAddress.Parse(txtIP.Text), port);//关联此IP和端口
Send(new UdpInfo() {Name = txtName.Text,Message = "上线了!", Types = });
Thread t = new Thread(new ThreadStart(Receices));
t.Start();
} public void Receices()//接收客户端的消息
{
while (true)
{
try
{
byte[] bytes = client.Receive(ref ipEndPoints);
UdpInfo u = DeserializeObject(bytes) as UdpInfo;
bd = new BindDelegate(BindRtb);
this.Invoke(bd, u);
}
catch (Exception)
{
client.Close();
}
}
}
public object DeserializeObject(byte[] pBytes)//反序列化二进制为对象
{
object newOjb = null;
if (pBytes == null)
return newOjb;
MemoryStream memory = new MemoryStream(pBytes);
memory.Position = ;
BinaryFormatter formatter = new BinaryFormatter();
newOjb = formatter.Deserialize(memory);
memory.Close();
return newOjb;
}
public byte[] SerializeObject(object pObj)//序列化对象为二进制的数
{
if (pObj == null)
return null;
MemoryStream memory = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memory, pObj);
memory.Position = ;
byte[] read = new byte[memory.Length];
memory.Read(read, , read.Length);
memory.Close();
return read;
}
public void BindRtb(UdpInfo u)//将消息添加到消息框中
{
if (u.Types == )
{
if (u.IsFist == true)
lvInfo.Items.Clear();
ListViewItem item = new ListViewItem(u.Name);
item.SubItems.Add(u.Ip);
item.SubItems.Add(u.Port);
lvInfo.Items.Add(item);
}
else if (u.Types == )//如果消息的类型是下线的话
{
IPEndPoint ipEndPoint = null;
foreach (ListViewItem items in lvInfo.Items)//循环每个成员
{
if (items.SubItems[].Text.Equals(u.Name))
{
IPAddress ip = IPAddress.Parse(items.SubItems[].Text);
ipEndPoint = new IPEndPoint(ip, Convert.ToInt32(items.SubItems[].Text));
lvInfo.Items.Remove(items);//从ListView集合中移除
continue;
}
}
}
foreach (ListViewItem items in lvInfo.Items)
{
if(items.SubItems[].Text.Equals(u.LoginName))
rtbMessage.Text += "\n" + u.Name + ":" + u.Message;
}
}
public void Send(UdpInfo u)//发送消息给服务器
{
byte[] bytes = SerializeObject(u);
client.Send(bytes, bytes.Length);
}
private void 结束程序ToolStripMenuItem_Click(object sender, EventArgs e)
{
Send(new UdpInfo() { Name = txtName.Text, Message = "下线了!", Types = });
client.Close();
Application.Exit();
} private void btnSend_Click(object sender, EventArgs e)
{
UdpInfo u = new UdpInfo() {
Name = txtName.Text, Message = rtbNews.Text, Types =
};
if (lvInfo.SelectedItems.Count > )//如果有选中的成员的话
{
u.Types = ;
u.ToName = lvInfo.SelectedItems[].SubItems[].Text;
}
Send(u);
lvInfo.SelectedItems.Clear();//清除上一次的痕迹
}
}
}

Udp通讯(零基础)的更多相关文章

  1. java基础55 UDP通讯协议和TCP通讯协议

    本文知识点(目录): 1.概述    2.UDP通讯协议    3.TCPP通讯协议 1.概述 1.在java中网络通讯作为Socket(插座)通讯,要求两台都必须安装socket.    2.不同的 ...

  2. IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

    1.系列文章引言 1.1 适合谁来阅读? 本系列文章尽量使用最浅显易懂的文字.图片来组织内容,力求通信技术零基础的人群也能看懂.但个人建议,至少稍微了解过网络通信方面的知识后再看,会更有收获.如果您大 ...

  3. IM开发者的零基础通信技术入门(一):通信交换技术的百年发展史(上)

    [来源申明]本文原文来自:微信公众号“鲜枣课堂”,官方网站:xzclass.com,原题为:<通信交换的百年沧桑(上)>,本文引用时已征得原作者同意.为了更好的内容呈现,即时通讯网在收录时 ...

  4. IM开发者的零基础通信技术入门(三):国人通信方式的百年变迁

    [来源申明]本文原文来自:微信公众号“鲜枣课堂”,官方网站:xzclass.com,原题为:<中国通信的百年沉浮>,本文引用时已征得原作者同意.为了更好的内容呈现,即时通讯网在收录时内容有 ...

  5. 如何从零基础学习VR

    转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 近期很多搞技术的朋友问我,如何步入VR的圈子?如何从零基础系统性的学习VR技术? 本人将于2017年1月 ...

  6. 零基础学习hadoop到上手工作线路指导

    零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...

  7. FFMPEG视音频编解码零基础学习方法-b

    感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...

  8. [总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  9. Hadoop 2.x从零基础到挑战百万年薪第一季

    鉴于目前大数据Hadoop 2.x被企业广泛使用,在实际的企业项目中需要更加深入的灵活运用,并且Hadoop 2.x是大数据平台处理 的框架的基石,尤其在海量数据的存储HDFS.分布式资源管理和任务调 ...

随机推荐

  1. 优秀前端开发教程:超炫的 Mobile App 3D 演示

    今天,我们想与您分享一个实验性的3D效果.它涉及到一个3D移动设备和一些移动应用程序截图.点击切换按钮时,我们将让移动设备转动并移动每个画面,使我们能看到一个分层的视图.你可能之前没见过这种应用程序演 ...

  2. Windows Azure Service Bus (6) 中继(Relay On) 使用VS2013开发Service Bus Relay On

    <Windows Azure Platform 系列文章目录> 注意:本文介绍的是国内由世纪互联运维的Windows Azure服务. 项目文件请在这里下载. 我们在使用Azure平台的时 ...

  3. jQuery DOM操作

    对节点的操作 查找节点 查找节点可以直接利用jQuery选择器来完成,非常便利. 插入节点 jQuery提供了8种插入节点的方法. 序号 方法 描述 实例 1 append() 向每个匹配的元素内部追 ...

  4. ES6 Features系列:Template Strings & Tagged Template Strings

    1. Brief ES6(ECMAScript 6th edition)于2015年7月份发布,虽然各大浏览器仍未全面支持ES6,但我们可以在后端通过Node.js 0.12和io.js,而前端则通过 ...

  5. 使用Graphviz绘图(一)

    前言 日常开发或者编写课程论文时,除了代码文档的编写,其中一个很重要的部分就是需要绘制流程图.示意图 绘制流程图有很多工具,一般常见的就有如下几种: Word.PPT等办公软件 Viso以及开源的Di ...

  6. Java泛型-类型擦除

    一.概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变 ...

  7. C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现

    今天做一个管理后台菜单,想着要用无限极分类,记得园子里还是什么地方见过这种写法,可今天找了半天也没找到,没办法静下心来自己写了: 首先创建节点类(我给它取名:AdminUserTree): /// & ...

  8. iOS学习笔记——iOS高级控件

    UITableView UITableView的样式有两种,一种是Grouped(左图),另一种是Plain(右图),如下图,它的属性是style,类型为UITableViewStyle,枚举值分别是 ...

  9. Android获取系统时间方法的总结

    Android获取系统时间方法的方法有很多种,常用的有Calendar.Date.currentTimeMills等方法. (1)Calendar Calendar获取系统时间首先要用Calendar ...

  10. WPS添加页码不是从首页开始

    A.页码从第二页开始 "插入"--"页码"--"格式"--不选"续前页"--"起始页码"设为0 &q ...