设计一个利用多播技术开展网络会议讨论的通信程序
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)    {    }  }}

 
  
					
				
评论