设计一个利用多播技术开展网络会议讨论的通信程序
using System;//知识点原理一定透彻using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Net;using System.Net.Sockets;using System.Threading;namespace 会议{ public partial class 多播会议讨论程序 : Form { Socket socket; Thread recvThread; IPAddress address = IPAddress.Parse("234.5.6.8"); IPEndPoint multiIPEndPoint; public 多播会议讨论程序()//窗体程序 { InitializeComponent(); this.txt.Text = ""; multiIPEndPoint = new IPEndPoint(address,6000);//234.5.6组号,成员通过套接字方法添加或删除成员 socket = new Socket(AddressFamily.InterNetwork ,SocketType.Dgram ,ProtocolType.Udp);//数据包套接字创建实例,创建组播成员的套接字socket IPEndPoint iep = new IPEndPoint(IPAddress.Any ,6000);//用ip,端口号定义一个网络端点【地址】,本机所有可用ip(防止多个ip) EndPoint ep = (EndPoint)iep; socket.Bind(iep);//将socket绑定到本地端点 socket.SetSocketOption(SocketOptionLevel.IP ,SocketOptionName.AddMembership ,new MulticastOption(address));//通过套接字的setSocketOption方法,将套接字加入到多播组或者从多播组退出 Control.CheckForIllegalCrossThreadCalls = false;//遇到线程交叉调用控制问题,请在调用线程之前,增加该语句 C#只有主线程才能操控控件,要想其他线程也操作,第一种方法:关闭安全检查。这句代码当然也就是关闭安全检测了!随着学习的深入,也不难知道,这种关闭安全性检查的方法是权宜之计,不宜使用在真正的项目实践中 recvThread = new Thread(new ThreadStart(ReceiveMessage));//启动线程,接收消息,receiveMseeage函数执行接收时多线程 recvThread.IsBackground = true;//设置该线程在后台运行 recvThread.Start();//启动线程的执行 byte[] bytes = System.Text.Encoding.Unicode.GetBytes("#");//使用“#”来标志成员加入的标志 socket.SendTo(bytes, SocketFlags.None, multiIPEndPoint);//向多播端点发送该数据,但是没有显示,然后接收方根据接收到的按标识位进行区别显示 } private void ReceiveMessage()//该函数主要是根据接收到的消息,按所发送的特殊标志位来区别显示 { EndPoint ep = (EndPoint)multiIPEndPoint; byte[] bytes = new byte[1024]; string str; int length; while (true)//循环接收【接收消息不知道什么时候对面发,所以循环】 { length = socket.ReceiveFrom(bytes,ref ep);//ref 带回发送方的端点 ipaddress.Any:6000 //下面2行是针对ref带回来的发送方端点 string epAddress = ep.ToString();//将端点(IP:端口号)转为字符串,因为传输时字符数组 epAddress = epAddress.Substring(0, epAddress.LastIndexOf(":"));//将:之前的提出来 substring(start,end)表示从start到end之间的字符串,包括start位置的字符但是不包括end位置的字符。https://www.jb51.net/article/44921.htm LastIndexOf:String 在此实例中的最后一个匹配项的索引位置。 //下面的处理对象是带标志位的接收到的数据 str = System.Text.Encoding.Unicode.GetString(bytes ,0 ,length);//字符数组转为字符串 switch (str[0]) { case '#'://有成员加入 this.listBox2.Items.Add("[" epAddress "]进入.");//box2消息显示窗口 会根据接收的消息得到epAddress,不管自己还是别人都收到接收到数据 string strl = "&:" epAddress;//现在strl变成了&:发送端的端点 for (int i = 0; i < this.listBox1.Items.Count; i )//在成员显示列Box1中 listBox1.Items.Count:这是得出列表框内的总项目数,将每一行给提出来 { strl = ":" this.listBox1.Items[i].ToString();//返回当前组件中的内容????? } byte[] users = System.Text.Encoding.Unicode.GetBytes(strl);//传输数据,使得每一个人都知道 socket.SendTo(users ,SocketFlags.None ,multiIPEndPoint);////////注意strl发送之后然后break,返回上面循环就变成str ,然后因为含有&所以进入case:语句隔开组成数组,然后 break; case '@': this.listBox2.Items.Add("[" epAddress "]退出.");//在@出现的时候已经传输数据,使得每一个人都知道,见下面 this.listBox1.Items.Remove(epAddress); break; case '&': string[] strArray = str.Split(':');//英文格式,上面的&:也必须英文格式:分隔符,返回str(是一开始带有标志位的数据,是别人发送的,receive是针对收到的数据,所以有时成员表出现&等是因为别人代码错了,发送的数据错了)各个被分开的子串 https://blog.csdn.net/riyuedangkong1/article/details/52431209 因为string[]所以数组,所以通过“:”来分割的每一段就是一个数组成员 for (int i = 1; i < strArray.Length; i )//遍历改数组,每一个成员、、从i=1开始因为要将分隔开后第一个是& 所以从1而非0 { bool isExist = false;//标志位 for (int j = 0; j < this.listBox1.Items.Count; j )//检测每一个成员{ if (strArray[i] == this.listBox1.Items[j].ToString())//相等表示成员中已经有了 { isExist = true; break; } } if (isExist == false)//如果没有该成员 { this.listBox1.Items.Add(strArray[i].Trim());//则将数组中的没有的一项加进去并去空格//该,改,去空格 } } break; case '!': this.listBox2.Items.Add("[" epAddress "]说:");//注意listbox1 2 是哪一个 this.listBox2.Items.Add(str.Substring(1)); this.listBox2.SelectedIndex = this.listBox2.Items.Count - 1; break; } } } private void 多播会议讨论程序_FormClosing(object sender, FormClosingEventArgs e) { byte[] bytes = System.Text.Encoding.Unicode.GetBytes("@");//使用“@”来标志成员成员的退出 socket.SendTo(bytes ,SocketFlags.None ,multiIPEndPoint);//向多播端点发送该数据,但是没有显示,然后接收方根据接收到的按标识位进行区别显示 recvThread.Abort(); socket.Close(); } private void txt_KeyPress(object sender, KeyPressEventArgs e)//这边也要该以哈yong keypress { if (e.KeyChar == (char)Keys.Return) { if (this.txt.Text.Trim().Length > 0) { byte[] bytes = System.Text.Encoding.Unicode.GetBytes("!" this.txt.Text);//使用“!”来代表发送消息 this.txt.Text = "";//清空输入的格子 socket.SendTo(bytes, SocketFlags.None, multiIPEndPoint);//向多播端点发送该数据,但是没有显示,然后接收方根据接收到的按标识位进行区别显示 } } } private void label1_Click(object sender, EventArgs e) { } }}
评论