Udp通讯(零基础)
前面学习了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通讯(零基础)的更多相关文章
- java基础55 UDP通讯协议和TCP通讯协议
本文知识点(目录): 1.概述 2.UDP通讯协议 3.TCPP通讯协议 1.概述 1.在java中网络通讯作为Socket(插座)通讯,要求两台都必须安装socket. 2.不同的 ...
- IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)
1.系列文章引言 1.1 适合谁来阅读? 本系列文章尽量使用最浅显易懂的文字.图片来组织内容,力求通信技术零基础的人群也能看懂.但个人建议,至少稍微了解过网络通信方面的知识后再看,会更有收获.如果您大 ...
- IM开发者的零基础通信技术入门(一):通信交换技术的百年发展史(上)
[来源申明]本文原文来自:微信公众号“鲜枣课堂”,官方网站:xzclass.com,原题为:<通信交换的百年沧桑(上)>,本文引用时已征得原作者同意.为了更好的内容呈现,即时通讯网在收录时 ...
- IM开发者的零基础通信技术入门(三):国人通信方式的百年变迁
[来源申明]本文原文来自:微信公众号“鲜枣课堂”,官方网站:xzclass.com,原题为:<中国通信的百年沉浮>,本文引用时已征得原作者同意.为了更好的内容呈现,即时通讯网在收录时内容有 ...
- 如何从零基础学习VR
转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 近期很多搞技术的朋友问我,如何步入VR的圈子?如何从零基础系统性的学习VR技术? 本人将于2017年1月 ...
- 零基础学习hadoop到上手工作线路指导
零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...
- FFMPEG视音频编解码零基础学习方法-b
感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...
- [总结]FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- Hadoop 2.x从零基础到挑战百万年薪第一季
鉴于目前大数据Hadoop 2.x被企业广泛使用,在实际的企业项目中需要更加深入的灵活运用,并且Hadoop 2.x是大数据平台处理 的框架的基石,尤其在海量数据的存储HDFS.分布式资源管理和任务调 ...
随机推荐
- 【原创】kafka controller源代码分析(一)
Kafka集群中的一个broker会被作为controller负责管理分区和副本的状态以及执行类似于重分配分区之类的管理任务.如果当前的controller失败了,会从剩下的broker中选出新的co ...
- 【转】 依赖注入框架Autofac的简单使用
Autofac是一款IOC框架,比较于其他的IOC框架,如Spring.NET,Unity,Castle等等所包含的,它很轻量级性能上也是很高的.于是,今天抽空研究了下它.下载地址:http://co ...
- node.js中使用https请求报CERT_UNTRUSTED的问题解决
只要调用了没有受信的https就会报错:CERT_UNTRUSTED 简单的解决方法就是设置环境变量回避非授信证书的问题. 只要在请求的代码之前加上如下代码即可: process.env.NODE_T ...
- 使用NuGet打包并发布至ProGet过程 (步骤详细,附python脚本)【上篇】
一.基本知识 (1)NuGet : NuGet是一个为大家所熟知的Visual Studio扩展,通过这个扩展,开发人员可以非常方便地在Visual Studio中安装或更新项目中所需要的第三方组件, ...
- Web API应用架构设计分析(2)
在上篇随笔<Web API应用架构设计分析(1)>,我对Web API的各种应用架构进行了概括性的分析和设计,Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端 ...
- HoverTree项目添加了查看留言列表功能
HoverTree项目添加了查看留言列表功能 页面:HoverTreeWeb项目下hvtpanel/usermessage/messagelist.aspx 添加留言页面:addmessage.asx ...
- 关于EF的 序列化类型为“XXX”的对象时检测到循环引用。
在用Ef的时候,也许经常会遇到循环引用的错误. 下面提供解决办法.(不是Json.Net,如果是Json.Net可以给导航属性通过增加特性标签来解决该问题) ef大多数问题,可以通过ToList()来 ...
- .Net(C#)最简单的邮件发送案例
一.序言 刚开始接触邮件发送功能的时候,在网上找的资料都挺复杂的!对于新手入门有点难(至少对于本人来说,第一次接触的时候确实不容易).这里就写一段简单的邮箱发送代码,备忘,也给新手一个参考(相关类的字 ...
- 【SQL】找出行数与自增标识值不相等的表(即有缺行)
环境:mssql ent 2k8 r2 原理:遍历所有含自增列的用户表,用sp_spaceused过程分别获取每张表的行数并写入临时表,然后使用IDENT_CURRENT函数获取表的最大标识值,比较二 ...
- ASP.NET防御XSS跨站攻击
目前做ASP.NET项目的时候就有遇到过“用户代码未处理HttpRequestValidationException:从客户端***中检测到有潜在危险的 Request.Form/Request.Qu ...