实例介绍
【实例简介】
实现udp群聊
【实例截图】

【核心代码】
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using CommonUntility;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Runtime.Serialization;
using CSharpWin;
using System.Drawing.Drawing2D;
using System.Text.RegularExpressions;
namespace LanChatterApp_ReConstruct_
{
public partial class MainFrm : Form
{
public MainFrm()
{
InitializeComponent();
}
public IPAddress broadIPAddress = IPAddress.Parse("255.255.255.255"); //组播地址
public static int lanPort = 11010; //端口号
public IPEndPoint iep;
public UdpClient listenClient = new UdpClient(lanPort);
public bool isRun = false; //监听是否启用的标志
public string localIP; //本机ip地址
public string localName; //本机名称
public string remoteIP; //远程主机ip地址
public string remoteName; //远程主机名称
public bool flag = false; //显示图片或者隐藏标志位
public bool emotionFlag = false;
#region RichTextBox线程与UI交互委托,用于添加文本内容及上色
/// <summary>
/// 添加聊天内容到聊天对话框中
/// </summary>
/// <param name="info">消息呈现内容</param>
/// <param name="titleOrContentFlag">标记:此信息是信息头还是信息内容,1代表是消息头,2代表是消息体</param>
/// <param name="selfOrOthersFlag">标记:此信息是自己发送的还是别人发送的,1代表是自己发送,2代表是别人发送</param>
private void AddTextBox(string info, int titleOrContentFlag, int selfOrOthersFlag)
{
if (1 == titleOrContentFlag) //如果是消息头
{
string title = info; if (1 == selfOrOthersFlag) //如果是自己发送
{
CommonUntility.RichTextBoxEx.AppendText(rAllContent, title, Color.Green);
}
else //如果是别人发送
{
CommonUntility.RichTextBoxEx.AppendText(rAllContent, title, Color.Blue);
}
}
else if (2 == titleOrContentFlag) //如果是消息体
{
string content = info;
CommonUntility.RichTextBoxEx.AppendText(rAllContent, content, Color.Black);
}
}
#endregion
private void mainFrm_Load(object sender, EventArgs e)
{
listenClient.EnableBroadcast = true; //允许发送和接受广播
iep = new IPEndPoint(broadIPAddress, lanPort);
lstUsers.Items.Add(" Computer IP---Computer Name");
openListeningThread(); //开启监听线程
SendInfoOnline();//发送上线广播信息
LoadingEmotion();
}
private void LoadingEmotion()
{
PictureBox[,] picList = new PictureBox[5,10];
for (int i = 0; i < 5; i )
{
for (int j = 0; j < 10; j )
{
int emotionSequenceCount = i * 10 j;
picList[i,j] = new PictureBox();
picList[i, j].Height = picList[i, j].Width = 24;
picList[i, j].Image = Image.FromFile(".\\Face2\\" emotionSequenceCount ".gif");
picList[i, j].Top = i * 24;
picList[i, j].Left = j * 24;
picList[i, j].Tag = "#(" emotionSequenceCount ")#";
picList[i, j].Parent = panImg;
picList[i, j].Click = new EventHandler((sender, e) =>
{
this.rSendContent.AppendText("#(" emotionSequenceCount ")#");
emotionFlag = false;
this.panImg.Visible = emotionFlag;
});
panImg.Controls.Add(picList[i,j]);
}
}
}
/// <summary>
/// 开启监听线程
/// </summary>
private void openListeningThread()
{
isRun = true;
Thread t = new Thread(new ThreadStart(() =>
{
IPEndPoint ipEnd = new IPEndPoint(broadIPAddress, lanPort);
try
{
while (isRun)
{
try
{
byte[] recInfo = listenClient.Receive(ref ipEnd); //接受内容,存储到byte数组中
DealWithAcceptedInfo(recInfo); //处理接收到的数据
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
} listenClient.Close(); isRun = false;
}
catch (SocketException se) { throw new Exception(se.Message); } //捕捉试图访问套接字时发生错误。
catch (ObjectDisposedException oe) { throw new Exception(oe.Message); } //捕捉Socket 已关闭
catch (InvalidOperationException pe) { throw new Exception(pe.Message); } //捕捉试图不使用 Blocking 属性更改阻止模式。
catch (Exception ex) { throw new Exception(ex.Message); }
}));
t.Start();
}
/// <summary>
/// 方法:处理接到的数据
/// </summary>
private void DealWithAcceptedInfo(byte[] recData)
{
BinaryFormatter formatter = new BinaryFormatter();
MessageModel recvMessage;
MemoryStream ms = new MemoryStream(recData);
try { recvMessage = (MessageModel)formatter.Deserialize(ms); }
catch (SerializationException e) { throw new Exception(e.Message); }
switch (recvMessage.Flag)
{
case "0x00": //用户上线
//这里很关键,当检测到一个新的用户上线,那么我们需要给这个新用户发送自己的机器消息,以便新用户能够自动添加进列表中。
SendInfoOnline(recvMessage.UserIp);
if (lstUsers.FindString(recvMessage.UserIp "---" recvMessage.UserName) <= 0) //如果用户不存在
{
lstUsers.Invoke((Action)(() => { lstUsers.Items.Add(recvMessage.UserIp "---" recvMessage.UserName); }));
lsbLog.Invoke((Action)(() => { lsbLog.Items.Add("User[" recvMessage.UserIp "] is online now!"); }));
}
break;
case "0x01": //用户聊天
rAllContent.Invoke((Action)(() =>
{
rAllContent.AppendText("\r\n");
AddTextBox(recvMessage.UserIp " " DateTime.Now "\r\n", 1, 2); //这是接收到了别人发来的信息
//AddTextBox(recvMessage.MsgContent "\r\n", 2, 2);//将发送的消息添加到窗体中
ParseEmotionInsert.AddContent(recvMessage.MsgContent, rAllContent);
rAllContent.AppendText("\r\n");
}));
break;
case "0x03": //用户下线
if (lstUsers.FindString(recvMessage.UserIp "---" recvMessage.UserName) > 0) //如果用户已经存在
{
MessageBox.Show(recvMessage.UserIp "---" recvMessage.UserName);
lstUsers.Invoke((Action)(() => { lstUsers.Items.Remove(recvMessage.UserIp "---" recvMessage.UserName); }));
lsbLog.Invoke((Action)(() => { lsbLog.Items.Add("User[" recvMessage.UserIp "] is offline now!"); }));
}
break;
default: break;
}
}
/// <summary>
/// 广播发送上线消息
/// </summary>
private void SendInfoOnline()
{
localIP = GetLocalIPandName.getLocalIP(); //得到本机ip
localName = GetLocalIPandName.getLocalName(); //得到本机的机器名称
MessageModel messageModel = new MessageModel();
messageModel.Flag = "0x00";
messageModel.UserIp = localIP;
messageModel.UserName = localName;
byte[] messageBytes = Parse.ToByteArray(messageModel);
SendInfoByIEP.SendInfoToAll(listenClient, messageBytes, iep);//发送广播上线信息
}
/// <summary>
/// 向单个ip发送上线消息
/// </summary>
/// <param name="remoteip"></param>
private void SendInfoOnline(string remoteip)
{
localIP = GetLocalIPandName.getLocalIP(); //得到本机ip
localName = GetLocalIPandName.getLocalName(); //得到本机的机器名称
MessageModel messageModel = new MessageModel();
messageModel.Flag = "0x00";
messageModel.UserIp = localIP;
messageModel.UserName = localName;
byte[] messageBytes = Parse.ToByteArray(messageModel);
IPEndPoint _iep = new IPEndPoint(IPAddress.Parse(remoteip), lanPort);
SendInfoByIEP.SendInfoToAll(listenClient, messageBytes, _iep); //发送广播上线信息
}
/// <summary>
/// 广播发送下线消息
/// </summary>
private void SendInfoOffline()
{
localIP = GetLocalIPandName.getLocalIP(); //得到本机ip
localName = GetLocalIPandName.getLocalName(); //得到本机的机器名称
MessageModel messageModel = new MessageModel();
messageModel.Flag = "0x03";
messageModel.UserIp = localIP;
messageModel.UserName = localName;
byte[] messageBytes = Parse.ToByteArray(messageModel);
SendInfoByIEP.SendInfoToAll(listenClient, messageBytes, iep); //发送广播下线信息
}
/// <summary>
/// 遍历列表,发送消息
/// </summary>
private void SendInfo(string data)
{
try
{
byte[] _data = Encoding.Default.GetBytes(data);
foreach (string s in lstUsers.Items) //遍历列表
{
if (s.Contains(".")) //确定包含的是ip地址
{
string _ip = s.Split('-')[0];
if (!_ip.Equals(localIP)) //将自身排除在外
{
IPEndPoint iepe = new IPEndPoint(IPAddress.Parse(_ip), lanPort); //套接字申明
//这里我们必须申明一个新的实例以避免重复接收问题。(如果利用原来的listenClient实例,将会造成重复接收。)
UdpClient udp = new UdpClient();
udp.Send(_data, _data.Length, iepe); //发送
}
}
}
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
private void SendInfo(byte[] data)
{
try
{
foreach (string s in lstUsers.Items) //遍历列表
{
if (s.Contains(".")) //确定包含的是ip地址
{
string _ip = s.Split('-')[0];
if (!_ip.Equals(localIP)) //将自身排除在外
{
IPEndPoint iepe = new IPEndPoint(IPAddress.Parse(_ip), lanPort); //套接字申明
//这里我们必须申明一个新的实例以避免重复接收问题。(如果利用原来的listenClient实例,将会造成重复接收。)
UdpClient udp = new UdpClient();
udp.Send(data, data.Length, iepe); //发送
}
}
}
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}
/// <summary>
/// “发送按钮”点击事件
/// </summary>
private void btnSend_Click(object sender, EventArgs e)
{
if (rSendContent.Text == "")
{
MessageBox.Show("Please fill in some words!","Notification",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
else
{
MessageModel messageModel = new MessageModel();
messageModel.Flag = "0x01";
messageModel.UserIp = localIP;
messageModel.UserName = localName;
messageModel.MsgContent = rSendContent.Text;
byte[] byteData = Parse.ToByteArray(messageModel);
SendInfo(byteData); //发送消息
rAllContent.AppendText(Environment.NewLine);
AddTextBox(localIP " " DateTime.Now "\r\n", 1, 1); //将发送的消息添加到窗体中
ParseEmotionInsert.AddContent(rSendContent.Text,rAllContent);
//AddTextBox(rSendContent.Text "\r\n", 2, 1); //将发送的消息添加到窗体中
this.rSendContent.Text = string.Empty; //清空发送内容
}
this.rAllContent.ScrollToCaret();
base.Invalidate(true);
}
/// <summary>
/// 点击退出时,发送下线消息
/// </summary>
private void mainFrm_FormClosing(object sender, FormClosingEventArgs e)
{
SendInfoOffline();
Environment.Exit(0); //用户退出
}
private void picEmotion_Click(object sender, EventArgs e)
{
emotionFlag = !emotionFlag;
panImg.Visible = emotionFlag;
}
}
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论