前面学习了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. Android性能测试工具(一)之Emmagee

    Android性能测试工具(一) 之Emmagee Emmagee是监控指定被测应用在使用过程中占用机器的CPU.内存.流量资源的性能测试小工具. 支持SDK:Android2.2以及以上版本 Emm ...

  2. Azure China (2) Azure China管理界面初探

    <Windows Azure Platform 系列文章目录> 首先是Q&A时间 1.我在Azure Global拥有测试账号或者免费的MSDN订阅账号,这个账号可以在国内Azur ...

  3. CSS布局:水平居中

    前言 一直对CSS布局一知半解,这段时间打算定下心来好好学习一下,于是先从最简单的水平居中布局开始入手.下面以分页组件为实例来记录各种实现方式. common.css <style type=& ...

  4. Git undo 操作

    相比传统的版本管理工具,git 的 undo 操作也不是很简单明了,本文尝试总结常用的 undo 操作. 重新提交 应该避免考虑不周全的提交,但这太难了.因此Git 专门提供了一个命令来弥补粗心的提交 ...

  5. 使用Dom4j进行XML解析

    1  概述 在进行ESB集成项目中,使用到了很多系统的接口,这些接口传输的数据大部分都采用了XML的格式,这样在使用ESB开发服务时就需要对XML数据进行解析或拼接的操作,本文以项目中流程服务为例,讲 ...

  6. 根据日期查询access数据库

    获取指定日期的记录 1.select Field1 from  A  where format("yyyy-MM-dd",Field1)=#2011-10-07# 有时不能获取记录 ...

  7. C#操作XML学习之创建XML文件的同时新建根节点和子节点(多级子节点)

    最近工作中遇到一个问题,要求创建一个XML文件,在创建的时候要初始化该XML文档,同时该文档打开后是XML形式,但是后缀名不是.在网上找了好些资料没找到,只能自己试着弄了一下,没想到成功了,把它记下来 ...

  8. JavaBean 的小知识点

    /** * @author http://roucheng.cnblogs.com * @version 2016-05-08 */ public class Person { private Str ...

  9. Windows线程漫谈界面线程和工作者线程

    每个系统都有线程,而线程的最重要的作用就是并行处理,提高软件的并发率.针对界面来说,还能提高界面的响应力. 线程分为界面线程和工作者线程,界面实际就是一个线程画出来的东西,这个线程维护一个“消息队列” ...

  10. jquery选择器(综合)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...