用C#语言做一个基于UDP的私聊和群聊工具

简介:
用C#语言做一个基于UDP的私聊和群聊工具
 
 
这个工具的最终界面:
 
测试界面:
 
 
 
 
 
 
 
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Collections;
namespace chat
{
    public partial class Form1 : Form
    {
        private bool isExit = false;
        private bool isShow = true;
        private bool m_bFlag;
         
        NotifyIcon myNotifyIcon;
        delegate void AppendStringCallback(string text);
        AppendStringCallback appendStringCallback;
        
        
        private UdpClient udpClient;
        private delegate void SetComboBoxCallback(string str);
        SetComboBoxCallback set_combobox_callback;
        public Form1()
        {
            InitializeComponent();
             appendStringCallback = new AppendStringCallback(AppendString);
             set_combobox_callback = new SetComboBoxCallback(SetComboBox);
             try
             {
                 m_Icon1 = new Icon("20005.ico");//导入图标文件 
                 m_Icon2 = new Icon("20060.ico");
             }
             catch (Exception e)
             {
                 MessageBox.Show("Error " + e.Message, "Animate Tray - Error");
               
             }
             m_bFlag = true;

         }
        #region connect_and_stop
        private void btnChat_Click(object sender, EventArgs e)
        {
            Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
            //将线程设为后台运行
            receiveThread.IsBackground = true;
            receiveThread.Start();
            btnChat.Enabled = false;
            btnStop.Enabled = true;
            txbSend.Enabled = true;
        }
        private void btnStop_Click(object sender, EventArgs e)
        {
            udpClient.Close();
            btnChat.Enabled = true;
            btnStop.Enabled = false;
            txbSend.Enabled = false;
        }
        #endregion
        #region Receive_events
        private void ReceiveData()
        {
            IsValidPort(txtPort.Text);
            
            try
            {
                //使用的接收端口号
                int port = int.Parse(txtPort.Text);
                udpClient = new UdpClient(port);
                //必须使用组播的地址范围内的地址
                IPAddress groupIP = IPAddress.Parse(groupIPaddress.Text);
                udpClient.JoinMulticastGroup(groupIP, 50);
               
            }
            catch
            { 
            
            }
            IPEndPoint remote = null;
            //接收从远程主机发送过来的信息
            while (true)
            {
                try
                {
                    //关闭udpClient时此句会产生异常
                    byte[] bytes = udpClient.Receive(ref remote);
                  string address = remote.ToString();
                    int atIndex = address.IndexOf(":");
                    string memberaddress = address.Substring(0, atIndex);
                    cbxChoose.Invoke(set_combobox_callback, memberaddress);
                    string str = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    AppendString(string.Format("来自{0}:{1}", remote, str));
                  
                }
                catch
                {
                    //退出循环,结束线程
                    break;
                }
            }
        }
        #endregion
        #region Send_events
        private void send(string IPadd, string Port)
        {

         UdpClient myUdpClient = new UdpClient();
         try
           {
            IPAddress add = IPAddress.Parse(IPadd);
            int port = int.Parse(Port);
            IPEndPoint iep = new IPEndPoint(add, port);
           
            int retry = 0;
            while (true)
            {
                try
                {
                    //将发送内容转换为字节数组
                    byte[] bytes = Encoding.UTF8.GetBytes(txbSend.Text);
                    //向子网发送信息
                    myUdpClient.Send(bytes, bytes.Length, iep);
                    AppendString(string.Format("发给{0}:{1}", iep, txbSend.Text));
                    txbSend.Clear();
                    txbSend.Focus();
                    break;
                }
                catch
                {
                    if (retry < 3)
                    {
                        retry++; continue;
                    }
                    else
                    {
                        MessageBox.Show("发送失败!");
                    }
                }
                finally
                {
                    myUdpClient.Close();
                }
            }
           }
         catch
           {
            }
               
        }
        private void btnSend_Click(object sender, EventArgs e)
        {
            //检测发送框的信息是不是为空 
            if (txbSend.Text=="")
            {
                MessageBox.Show("发送信息不能为空");
                return;
            }
            IsValidPort(txtPort.Text);
            
            UdpClient myUdpClient = new UdpClient();
            
            int index = cbxChoose.SelectedIndex;
            if (txtIPaddree.Text == ""&& (index==0 || index==-1))
            {
                IsValidIP(groupIPaddress.Text);
               
                try
                {
                 

                   IPAddress add = IPAddress.Parse(groupIPaddress.Text);
                   int port = Convert.ToInt32(txtPort.Text);
                    IPEndPoint iep = new IPEndPoint(add, port);
                   //将发送内容转换为字节数组
                   byte[] bytes = Encoding.UTF8.GetBytes(txbSend.Text);
                   //向子网发送信息
                   myUdpClient.Send(bytes, bytes.Length, iep);
                   txbSend.Clear();
                   txbSend.Focus();
                   
                }
                catch 
                {
                    MessageBox.Show( "发送失败");
                }
                finally
                {
                    myUdpClient.Close();
                }
            }
            else if (index == 0 || index == -1)
            {
                IsValidIP(txtIPaddree.Text);
            
                    send(txtIPaddree.Text, txtPort.Text);
               
            }
            else 
            {
                
                send(cbxChoose.Text, txtPort.Text);
            }
 
        }

        #endregion
        #region IsValid_field
        //检测输入对方IP有没有效
        private void IsValidIP(string str)
        {
            IPAddress ip;
            if (!IPAddress.TryParse(str, out ip))
            {
                MessageBox.Show("非法IP地址");
              
                return;
            }
        }
        //检测端口号有没有效
        private void IsValidPort(string str)
        {
            int isPort;
 
            if (txtPort.Text == "")
            {
                MessageBox.Show("端口号不能为空");
                return;
            }
            else if (!int.TryParse(str, out isPort))
            {
                MessageBox.Show("端口号无效");
                return;
            }
            else if ((isPort < 1024) || (isPort > 65335))
            {
                MessageBox.Show("端口号应该大于或等于1024,小于或等于65535");
                return;
            }
        }
        #endregion
        #region tray_field
        private void Form1_Load(object sender, EventArgs e)
        {
            btnChat.Enabled = true;
            btnStop.Enabled = false;
            txbSend.Enabled = false;
            cbxChoose.SelectedIndex = 0;
            //在当前窗体的容器中创建托盘图标NotifyIcon的实例
            myNotifyIcon = new NotifyIcon(this.components);
            //指定托盘图标
            myNotifyIcon.Icon = new Icon("1644.ico");
            //鼠标悬停在托盘图标上方时显示的内容
            myNotifyIcon.Text = "我的聊天器";
            //设置关联的上下文菜单
            myNotifyIcon.ContextMenuStrip = this.contextMenuStrip1;
            //显示托盘图标
            myNotifyIcon.Visible = true;
            //添加用户双击任务栏中的托盘图标时触发的事件
            myNotifyIcon.DoubleClick += new EventHandler(myNotifyIcon_DoubleClick);
        }
        void myNotifyIcon_DoubleClick(object sender, EventArgs e)
        {
            if (isShow)
            {
                this.Hide();
                isShow = false;
            }
            else
            {
                this.Show();
                isShow = true;
            }
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (isExit == false)
            {
                //取消关闭窗体事件
                e.Cancel = true;
                //隐藏窗体
                this.Hide();
            }
            else
            {
                udpClient.Close();
            }
        }
        private void 显示窗口toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            this.Show();
        }
        private void 退出程序toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            isExit = true;
            Application.Exit();
        }
        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            if (isShow)
            {
                this.Hide();
                isShow = false;
            }
            else
            {
                this.Show();
                isShow = true;
            }
        }
        private Icon m_Icon1;
        private Icon m_Icon2;
        private void 打开计时器ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tmIcon.Start();
        }
        private void 停止计时器ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tmIcon.Stop();
        }
        private void tmIcon_Tick(object sender, EventArgs e)
        {
            if (m_Icon1 != null && m_Icon2 != null) //如果两个图标文件都被正确载入 
            {
                //只要tmIcon被启动,则在两个图标之间不断进行选择变换,实现动画效果 
                if (m_bFlag == true)
                {
                    notifyIcon1.Icon = m_Icon2;
                    m_bFlag = false;
                }
                else
                {
                    notifyIcon1.Icon = m_Icon1;
                    m_bFlag = true;
                }
            }
        }
        #endregion
        #region control_delegate_method
        private void AppendString(string text)
        {
            if (rtbMessage.InvokeRequired)
            {
                rtbMessage.Invoke(appendStringCallback, text);
            }
            else
            {
                rtbMessage.AppendText(text + "\r\n");
            }
        }
        private void SetComboBox(string str)
        {
            //去除掉cbxChoose控件选项的重复内容
            cbxChoose.Items.Add(str);
            for (int i = 0; i < this.cbxChoose.Items.Count; i++) 
            { 
                for (int j = 1; j < this.cbxChoose.Items.Count - 1; j++)
                { 
                    if (this.cbxChoose.Items[i].ToString() == this.cbxChoose.Items[j].ToString())
                    { this.cbxChoose.Items.Remove(this.cbxChoose.Items[j]);
                    } 
                } 
            }
        }
        #endregion
        private void button1_Click(object sender, EventArgs e)
        {
            rtbMessage.Clear();
        }
 
 
 
 

    }
}


本文转自gauyanm 51CTO博客,原文链接:http://blog.51cto.com/gauyanm/343689,如需转载请自行联系原作者
相关文章
|
4月前
|
前端开发 Java C#
java/C#语言开发的医疗信息系统11套源码
java/C#语言开发的医疗信息系统11套源码
79 2
|
4月前
|
存储 安全 Java
C#语言特点及基础
C#语言特点及基础
|
4月前
|
自然语言处理 C# Windows
C#开源免费的Windows右键菜单管理工具
C#开源免费的Windows右键菜单管理工具
|
10天前
|
存储 开发框架 .NET
C#语言究竟隐藏了哪些秘密?一文带你揭开编程界的神秘面纱
【8月更文挑战第22天】C#是微软推出的面向对象编程语言,以其简洁的语法和强大的功能,在软件开发领域占据重要地位。作为一种强类型语言,C#确保了代码的可读性和可维护性。它支持多种数据类型,如整型、浮点型及复合类型如类和结构体。类是核心概念,用于定义对象的属性和行为。C#还包括方法、异常处理、集合类型如列表和字典,以及泛型和LINQ等高级特性,支持异步编程以提高应用响应性。.NET Core的推出进一步增强了C#的跨平台能力。
35 3
|
4月前
|
IDE C# 开发工具
一个开源轻量级的C#代码格式化工具(支持VS和VS Code)
一个开源轻量级的C#代码格式化工具(支持VS和VS Code)
138 6
|
3天前
|
JSON C# 开发者
💡探索C#语言进化论:揭秘.NET开发效率飙升的秘密武器💼
【8月更文挑战第28天】C#语言凭借其强大的功能与易用性深受开发者喜爱。伴随.NET平台演进,C#持续引入新特性,如C# 7.0的模式匹配,让处理复杂数据结构更直观简洁;C# 8.0的异步流则使异步编程更灵活高效,无需一次性加载全部数据至内存。通过示例展示了模式匹配简化JSON解析及异步流实现文件逐行读取的应用。此外,C# 8.0还提供了默认接口成员和可空引用类型等特性,进一步提高.NET开发效率与代码可维护性。随着C#的发展,未来的.NET开发将更加高效便捷。
10 1
|
2月前
|
存储 Oracle 关系型数据库
PACS源码,C#语言数字医学影像系统成品源码
**数字医学影像系统(RIS/PACS)**采用C#开发,基于C/S架构,配Oracle数据库,具备自主版权,适用于项目实施。系统包含分诊、超声、放射、内镜、病理等工作站,支持基本信息维护、报表查询和系统维护。功能亮点有:WorkList管理、影像采集传输、存储检索、图像处理、多序列浏览、流程控制、报告录入与审核、支持多种影像设备及高级影像处理。RIS与PACS数据库同步,并集成HIS、电子病历等系统接口。全面遵循DICOM3.0标准。
PACS源码,C#语言数字医学影像系统成品源码
|
12天前
|
程序员 C#
C# 语言类型全解
C# 语言类型全解
10 0
|
12天前
|
开发框架 .NET C#
C#语言进阶(四) 枚举器和迭代器
C#语言进阶(四) 枚举器和迭代器
21 0