Socket案例

来源:互联网 发布:淘宝哪家莆田鞋好 编辑:程序博客网 时间:2024/04/29 11:15

服务器端:

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace EasyChat_Server
{
    class Listener
    {

        #region 字段定义

        /// <summary>
        /// 服务器程序使用的端口,默认为8888
        /// </summary>
        private int _port = 8888;

        /// <summary>
        /// 接收数据缓冲区大小64K
        /// </summary>
        private const int _maxPacket = 64 * 1024;

        /// <summary>
        /// 服务器端的监听器
        /// </summary>
        private TcpListener _tcpl = null;

        /// <summary>
        /// 保存所有客户端会话的哈希表
        /// </summary>
        private Hashtable _transmit_tb = new Hashtable();

        #endregion
       

        #region 服务器方法

        /// <summary>
        /// 关闭监听器并释放资源
        /// </summary>
        public void Close()
        {
            if (_tcpl != null)
            {
                _tcpl.Stop();//如果不为空 就停止 tcplistener
            }
            //关闭客户端连接并清理资源
            if (_transmit_tb.Count != 0)//客户端会话的哈希表
            {
                foreach (Socket session in _transmit_tb.Values)
                {
                    session.Shutdown(SocketShutdown.Both);
                }
                _transmit_tb.Clear();
                _transmit_tb = null;
            }
        }

 

        /// <summary>
        /// 配置监听端口号
        /// </summary>
        public void GetConfig()
        {
            string portParam;
            Console.Write("请输入监听端口,直接回车则接受默认端口8888: ");
            //portParam = Console.ReadLine();
            portParam = Console.ReadLine();

            if (portParam != string.Empty)
            {
                if (!int.TryParse(portParam, out _port) || _port < 1023 || _port > 65535)//很是精炼的语句
                {
                    _port = 8888;
                    Console.WriteLine("端口号不合法,默认端口号被接受!");
                }
            }
        }

        /// <summary>
        /// 序列化在线列表,向客户端返回序列化后的字节数组
        /// </summary>
        /// <returns>序列化后的字节数组</returns>
        private byte[] SerializeOnlineList()
        {
            StringCollection onlineList = new StringCollection();
            foreach (object o in _transmit_tb.Keys)
            {
                onlineList.Add(o as string);//转换语句
            }
            IFormatter format = new BinaryFormatter();//以二进制格式将对象或整个连接对

                                                      //象图形序列化和反序列化。
            MemoryStream stream = new MemoryStream();//创建其支持存储区为内存的流
            format.Serialize(stream, onlineList);    //保持到内存流 将对象或具有给定根的对象图形序列化为所提供的流
            byte[] ret = stream.ToArray();           //
            stream.Close();
            return ret;
        }

        /// <summary>
        /// 提取命令
        /// 格式为两个一位整数拼接成的字符串。
        /// 第一位为0表示客户机向服务器发送的命令,为1表示服务器向客户机发送的命令。
        /// 第二位表示命令的含义,具体如下:
        /// "01"-离线
        /// "02"-请求在线列表
        /// "03"-请求对所有人闪屏振动
        /// "04"-请求对指定用户闪屏振动
        /// "05"-请求广播消息
        /// default-转发给指定用户
        /// </summary>
        /// <param name="s">要解析的包含命令的byte数组,只提取前两个字节</param>
        /// <returns>拼接成的命令</returns>
        private string DecodingBytes(byte[] s)
        {
            return string.Concat(s[0].ToString(), s[1].ToString());
        }

        /// <summary>
        /// 线程执行体,转发消息-------------------
        /// </summary>
        /// <param name="obj">传递给线程执行体的用户名,用以与用户通信</param>
        private void ThreadFunc(object obj)
        {
            //通过转发表得到当前用户套接字
            Socket clientSkt = _transmit_tb[obj] as Socket;
            while (true)
            {
                try
                {
                    //接受第一个数据包。
                    //仅有两种情况,一为可以识别的命令格式,否则为要求转发给指定用户的用户名。
                    //这里的实现不够优雅,但不失为此简单模型的一个解决之道。
                    byte[] _cmdBuff = new byte[128];
                    clientSkt.Receive(_cmdBuff);
                    string _cmd = DecodingBytes(_cmdBuff);
                    /// "01"-离线
                    /// "02"-请求在线列表
                    /// "03"-请求对所有人闪屏振动
                    /// "04"-请求对指定用户闪屏振动
                    /// "05"-请求广播消息
                    /// default-转发给指定用户
                    switch (_cmd)
                    {
                        case "01":
                            {
                                _transmit_tb.Remove(obj);
                                string svrlog = string.Format("用户 {0} 在 {1} 已断开... 当前在线人数: {2}/r/n/r/n", obj, DateTime.Now, _transmit_tb.Count);
                                Console.WriteLine(svrlog);
                                //向所有客户机发送系统消息
                                foreach (DictionaryEntry de in _transmit_tb)
                                {
                                    string _clientName = de.Key as string;
                                    Socket _clientSkt = de.Value as Socket;
                                    _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));//给其他用户通知现在上线的用户
                                }
                                Thread.CurrentThread.Abort();
                                break;
                            }
                        case "02":
                            {
                                byte[] onlineBuff = SerializeOnlineList();
                                //先发送响应信号,用于客户机的判断,"11"表示服务发给客户机的更新在线列表的命令
                                clientSkt.Send(new byte[] { 1, 1 });
                                clientSkt.Send(onlineBuff);
                                break;
                            }
                        case "03"://向每个用户发送
                            {
                                string displayTxt = string.Format("用户{0}发送了一个闪屏振动。/r/n/r/n", obj);
                                foreach (DictionaryEntry de in _transmit_tb)
                                {
                                    string _clientName = de.Key as string;
                                    Socket _clientSkt = de.Value as Socket;
                                    if (!_clientName.Equals(obj))
                                    {
                                        //先发送响应信号,用于客户机的判断,"12"表示服务发给客户机的闪屏振动的命令
                                        _clientSkt.Send(new byte[] { 1, 2 });
                                        _clientSkt.Send(Encoding.Unicode.GetBytes(displayTxt));
                                    }
                                }
                                break;
                            }
                        case "04"://向指定用户发送
                            {
                                string _receiver = null;
                                byte[] _receiverBuff = new byte[128];
                                clientSkt.Receive(_receiverBuff);//获取指定用户名
                                _receiver = Encoding.Unicode.GetString(_receiverBuff).TrimEnd('/0');
                                string displayTxt = string.Format("用户 {0} 发送了一个闪屏振动。/r/n/r/n", obj);
                                //通过转发表查找接收方的套接字
                                if (_transmit_tb.ContainsKey(_receiver))
                                {
                                    Socket receiverSkt = _transmit_tb[_receiver] as Socket;
                                    receiverSkt.Send(new byte[] { 1, 2 });
                                    receiverSkt.Send(Encoding.Unicode.GetBytes(displayTxt));
                                }
                                else
                                {
                                    string sysMessage = string.Format("[系统消息]您刚才的闪屏振动没有发送成功。/r/n可能原因:用户 {0} 已离线或者网络阻塞。/r/n/r/n", _receiver);
                                    clientSkt.Send(Encoding.Unicode.GetBytes(sysMessage));
                                }
                                break;
                            }
                        case "05":
                            {
                                byte[] _msgBuff = new byte[_maxPacket];
                                clientSkt.Receive(_msgBuff);
                                foreach (DictionaryEntry de in _transmit_tb)
                                {
                                    string _clientName = de.Key as string;
                                    Socket _clientSkt = de.Value as Socket;
                                    if (!_clientName.Equals(obj))
                                    {
                                        _clientSkt.Send(_msgBuff);
                                    }
                                }
                                break;
                            }
                        default:
                            {
                                //以上都不是则表明第一个包是接收方用户名,继续接受第二个消息正文数据包
                                string _receiver = Encoding.Unicode.GetString(_cmdBuff).TrimEnd('/0');
                                byte[] _packetBuff = new byte[_maxPacket];
                                clientSkt.Receive(_packetBuff);
                                if (_transmit_tb.ContainsKey(_receiver))
                                {
                                    //通过转发表查找接收方的套接字
                                    Socket receiverSkt = _transmit_tb[_receiver] as Socket;
                                    receiverSkt.Send(_packetBuff);
                                }
                                else
                                {
                                    string sysMessage = string.Format("[系统消息]您刚才的内容没有发送成功。/r/n可能原因:用户 {0} 已离线或者网络阻塞。/r/n/r/n", _receiver);
                                    clientSkt.Send(Encoding.Unicode.GetBytes(sysMessage));
                                }
                                break;
                            }
                    }
                }
                catch (SocketException)
                {
                    _transmit_tb.Remove(obj);
                    string svrlog = string.Format("用户 {0} 的客户端在 {1} 意外终止!当前在线人数:{2}/r/n/r/n", obj, DateTime.Now, _transmit_tb.Count);
                    Console.WriteLine(svrlog);
                    //向所有客户机发送系统消息
                    foreach (DictionaryEntry de in _transmit_tb)
                    {
                        string _clientName = de.Key as string;
                        Socket _clientSkt = de.Value as Socket;
                        _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));
                    }
                    Console.WriteLine();
                    Thread.CurrentThread.Abort();
                }
            }
        }

        /// <summary>
        /// 启动监听,轮询监听客户机请求并将客户端套接字存入转发表
        /// </summary>
        public void StartUp()
        {
            IPAddress _ip = Dns.GetHostAddresses(Dns.GetHostName())[0];//可能有多个,此时的IP是本地IP
            _tcpl = new TcpListener(_ip, _port);
            _tcpl.Start();//开始侦听传入的连接请求。
            Console.WriteLine("服务器已启动,正在监听.../n");
            Console.WriteLine(string.Format("服务器IP:{0}/t端口号:{1}/n", _ip, _port));
            while (true)
            {
                byte[] packetBuff = new byte[_maxPacket];// 接收数据缓冲区大小64K

                //AcceptSocket 是一个阻止方法,该方法返回可用于发送和接收数据的 Socket。
                //返回的 Socket 是使用远程主机的 IP 地址和端口号初始化的。
                //您可以使用 Socket 类中任何可用的 Send 和 Receive 方法与远程主机进行通信。
             
                Socket newClient = _tcpl.AcceptSocket();//本地TcpListener 接受新的请求
                //返回的 Socket 是使用远程主机的 IP 地址和端口号初始化的

                newClient.Receive(packetBuff);//将接受的远程SOCKET,将数据存入接受缓冲区
                string userName = Encoding.Unicode.GetString(packetBuff).TrimEnd('/0');

                //验证是否为唯一用户,有了就发送失败命令给请求客户
                if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(userName))
                {
                    newClient.Send(Encoding.Unicode.GetBytes("cmd::Failed"));
                    continue;
                }
                else
                {
                    newClient.Send(Encoding.Unicode.GetBytes("cmd::Successful"));
                }

                //将新连接加入转发表并创建线程为其服务
                _transmit_tb.Add(userName, newClient);

                string svrlog = string.Format("用户 {0} 在 {1} 已连接... 当前在线人数: {2}/r/n/r/n", userName, DateTime.Now, _transmit_tb.Count);
                Console.WriteLine(svrlog);
             

                Thread clientThread = new Thread(new ParameterizedThreadStart(ThreadFunc));
                clientThread.Start(userName);
              
            }
        }

        #endregion
    }
}

 

 

 

 

 

客户端:

 

登录:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;

namespace EasyChat
{
    public partial class login_frm : Form
    {
        /// <summary>
        /// IP地址
        /// </summary>
        private IPAddress _ipAddr;

        #region 登录窗体构造函数

        /// <summary>
        /// 构造函数,自动生成
        /// </summary>
        public login_frm()
        {
            InitializeComponent();
        }

        #endregion

        #region 登录窗体的私有方法

        /// <summary>
        /// 验证登录信息
        /// </summary>
        /// <returns>验证结果</returns>
        private bool ValidateInfo()
        {
            if (user_tb.Text.Trim() == string.Empty)
            {
                MessageBox.Show("请填写用户名!",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                return false;
            }

            if (!IPAddress.TryParse(svrip_tb.Text, out _ipAddr))
            {
                MessageBox.Show("IP地址不合法!",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                return false;
            }
            int _port;
            if (!int.TryParse(svrport_tb.Text, out _port))
            {
                MessageBox.Show("端口号不合法!",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                return false;
            }
            else
            {
                if (_port < 1024 || _port > 65535)
                {
                    MessageBox.Show("端口号不合法!",
                                    "提示",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 取消,关闭窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cancel_btn_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void login_btn_Click(object sender, EventArgs e)
        {
            //验证数据合法性
            if (!ValidateInfo())
            {
                return;
            }
            int port = int.Parse(svrport_tb.Text);
            //向服务器发出连接请求
            TCPConnection conn = new TCPConnection(_ipAddr, port);
            TcpClient _tcpc = conn.Connect();
            if (_tcpc == null)
            {
                MessageBox.Show("无法连接到服务器,请重试!",
                                "错误",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
            else
            {
                NetworkStream netstream = _tcpc.GetStream();//提供用于访问网络的基本数据流
                //向服务器发送用户名以确认身份
                netstream.Write(Encoding.Unicode.GetBytes(user_tb.Text), 0, Encoding.Unicode.GetBytes(user_tb.Text).Length);
                //得到登录结果
                byte[] buffer = new byte[50];
                netstream.Read(buffer, 0, buffer.Length);//该方法将数据读入 buffer 参数并返回成功读取的字节数。如果没有可以读取的数据,则 Read 方法返回 0。
                string connResult = Encoding.Unicode.GetString(buffer).TrimEnd('/0');
                if (connResult.Equals("cmd::Failed"))
                {
                    MessageBox.Show("您的用户名已经被使用,请尝试其他用户名!",
                                    "提示",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                    return;
                }
                else
                {
                    string svrskt = svrip_tb.Text + ":" + svrport_tb.Text;
                    chat_frm chatFrm = new chat_frm(user_tb.Text, netstream, svrskt);//一个巧妙的参数传递方法
                    chatFrm.Owner = this;
                    this.Hide();
                    chatFrm.Show();
                }
            }
        }

        /// <summary>
        /// 初始化登录信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void login_frm_Load(object sender, EventArgs e)
        {
            svrip_tb.Text = "10.1.10.153";
            svrport_tb.Text = "8888";
            user_tb.Focus();
        }

        #endregion
    }
}

 

 

聊天:

 

using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Net.Sockets;//++++
using System.Windows.Forms;
using System.Threading;//++++
using System.Runtime.Serialization;//++++
using System.Runtime.InteropServices;//++++
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;//++++
using System.Media;//+++++

namespace EasyChat
{
    public partial class chat_frm : Form
    {

        #region 私有字段

        /// <summary>
        /// 当前用户名
        /// </summary>
        private string _username = null;

        /// <summary>
        /// 数据缓冲区大小
        /// </summary>
        private int _maxPacket = 2048;//2K的缓冲区

        /// <summary>
        /// 用于接受消息的线程
        /// </summary>
        private Thread _receiveThread = null;

        /// <summary>
        /// 用于接受和发送的网络流,从登录窗体得到
        /// </summary>
        private NetworkStream _nws = null;

        /// <summary>
        /// 服务器套接字的字符串形式,从登录窗体得到
        /// </summary>
        private string _svrskt = null;

        /// <summary>
        /// 播放消息提示的播放器
        /// </summary>
        private SoundPlayer _sp1 = new SoundPlayer(Properties.Resources.msg);
        private SoundPlayer _sp2 = new SoundPlayer(Properties.Resources.nudge);
        /// <summary>
        /// 指示是否最小化到托盘
        /// </summary>
        private bool _hideFlag = false;

        #endregion


        #region 聊天窗体构造函数

        /// <summary>
        /// 构造函数,得到登录窗体的一些信息
        /// </summary>
        /// <param name="userName">当前用户名</param>
        /// <param name="nws">接受和发送消息的网络流</param>
        /// <param name="svrskt">服务器套接字的字符串形式</param>
        public chat_frm(string userName, NetworkStream nws, string svrskt)
        {
            InitializeComponent();
            _username = userName;
            _nws = nws;
            _svrskt = svrskt;
        }

        #endregion


        #region 聊天窗体的私有方法

        /// <summary>
        /// 保存聊天记录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void save_btn_Click(object sender, EventArgs e)
        {
            DialogResult ret;
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "文本文件(*.txt)|*.txt";
            sfd.AddExtension = true;
            if ((ret = sfd.ShowDialog()) == DialogResult.OK)
            {
                chatrcd_rtb.SaveFile(sfd.FileName, RichTextBoxStreamType.PlainText);
            }
        }

        /// <summary>
        /// 清除聊天记录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void clear_btn_Click(object sender, EventArgs e)
        {
            DialogResult ret;
            ret = MessageBox.Show("确定清除吗?清除后不可恢复。",
                                  "提示",
                                  MessageBoxButtons.OKCancel,
                                  MessageBoxIcon.Question,
                                  MessageBoxDefaultButton.Button2);

            if (ret == DialogResult.OK)
            {
                chatrcd_rtb.Clear();
            }
        }

        /// <summary>
        /// 向服务器发送离线请求,结束接受消息线程,清理资源并关闭父窗体和自身窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void close_btn_Click(object sender, EventArgs e)
        {
            DialogResult ret;
            ret = MessageBox.Show("确定与服务器断开连接吗?",
                                  "退出",
                                  MessageBoxButtons.OKCancel,
                                  MessageBoxIcon.Question,
                                  MessageBoxDefaultButton.Button2);

            if (ret == DialogResult.OK)
            {
                //向服务器发送离线请求
                _nws.Write(new byte[] { 0, 1 }, 0, 2);
                //结束接受消息的线程
                if (_receiveThread != null)
                {
                    _receiveThread.Abort();
                }
                //关闭网络流
                _nws.Close();
                //关闭父窗口及自身===========
                this.Owner.Close();
                this.Close();
            }
        }

        /// <summary>
        /// 提取命令
        /// 格式为两个一位整数拼接成的字符串。
        /// 第一位为0表示客户机向服务器发送的命令,为1表示服务器向客户机发送的命令。
        /// 第二位表示命令的含义,具体如下:
        /// "11"-服务器要求客户机更新在线列表
        /// "12"-服务器要求客户机做闪屏振动
        /// default-接受用户消息或者系统消息的正文
        /// </summary>
        /// <param name="s">要解析的包含命令的byte数组,只提取前两个字节</param>
        /// <returns>拼接成的命令</returns>
        private string DecodingBytes(byte[] s)
        {
            return string.Concat(s[0].ToString(), s[1].ToString());
        }

        /// <summary>
        /// 接受消息的线程执行体
        /// </summary>
        private void ReceiveMsg()
        {
            while (true)
            {
                byte[] packet = new byte[_maxPacket];
                _nws.Read(packet, 0, packet.Length);
                string _cmd = DecodingBytes(packet);

                switch (_cmd)
                {
                    /// "11"-服务器要求客户机更新在线列表
                    /// "12"-服务器要求客户机做闪屏振动
                    /// default-接受用户消息或者系统消息的正文
                    case "11":
                        {
                            byte[] onlineBuff = new byte[_maxPacket];
                            int byteCnt = _nws.Read(onlineBuff, 0, onlineBuff.Length);
                            IFormatter format = new BinaryFormatter();
                            MemoryStream stream = new MemoryStream();
                            stream.Write(onlineBuff, 0, byteCnt);
                            stream.Position = 0;
                            StringCollection onlineList = (StringCollection)format.Deserialize(stream);
                            online_cb.Items.Clear();
                            foreach (string onliner in onlineList)
                            {
                                if (!onliner.Equals(_username))
                                {
                                    online_cb.Items.Add(onliner);
                                }
                            }
                            break;
                        }
                    case "12":
                        {
                            Nudge();
                            break;
                        }
                    default:
                        {
                            string displaytxt = Encoding.Unicode.GetString(packet);
                            chatrcd_rtb.AppendText(displaytxt);
                            _sp1.Play();
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// 启动接受消息线程并显示相关信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chat_frm_Load(object sender, EventArgs e)
        {
            _receiveThread = new Thread(new ThreadStart(ReceiveMsg));
            _receiveThread.Start();
            online_cb.Enabled = false;
            user_lb.Text = "当前用户:" + _username;
            svrskt_lb.Text = "服务器:" + _svrskt;
        }

        /// <summary>
        /// 通过窗体右上角关闭窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chat_frm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;
            }
            if (e.CloseReason == CloseReason.FormOwnerClosing)
            {
                return;
            }
            close_btn_Click(sender, e);
        }

        /// <summary>
        /// 发送消息,将接受方用户名和消息正文分开发送,便于服务器端处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void send_btn_Click(object sender, EventArgs e)
        {
            string localTxt = null;
            string sendTxt = null;
            string msg = msg_tb.Text.Trim();
            if (msg == string.Empty)
            {
                MessageBox.Show("不能发送空消息",
                                "提示",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                return;
            }

            //如果是聊天室模式则向服务器发送广播请求
            if (broadcast_rb.Checked)
            {
                localTxt = string.Format("[广播]您在 {0} 对所有人说:/r/n{1}/r/n/r/n", DateTime.Now, msg);
                sendTxt = string.Format("[广播]{0} 在 {1} 对所有人说:/r/n{2}/r/n/r/n", _username, DateTime.Now, msg);
                //发送广播请求
                _nws.Write(new byte[] { 0, 5 }, 0, 2);
            }
            else
            {
                string _receiver = online_cb.Text;
                if (_receiver == string.Empty)
                {
                    MessageBox.Show("请选择一个接收者!/n如果没有接受者可选,表明当前只有您一个人在线/t",
                                    "发送消息",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                    return;
                }
                localTxt = string.Format("[私聊]您在 {0} 对 {1} 说:/r/n{2}/r/n/r/n", DateTime.Now, _receiver, msg);
                sendTxt = string.Format("[私聊]{0} 在 {1} 对您说:/r/n{2}/r/n/r/n", _username, DateTime.Now, msg);
                //发送接受者用户名
                _nws.Write(Encoding.Unicode.GetBytes(_receiver), 0, Encoding.Unicode.GetBytes(_receiver).Length);
            }
            _nws.Write(Encoding.Unicode.GetBytes(sendTxt), 0, Encoding.Unicode.GetBytes(sendTxt).Length);

            chatrcd_rtb.AppendText(localTxt);
            msg_tb.Clear();
        }

        /// <summary>
        /// 有新消息来时闪烁任务栏并且保持聊天记录内容滚动到最底端,QQ就是这么玩滴~
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        [DllImport("user32.dll")]
        public static extern bool FlashWindow(IntPtr hWnd, bool bInvert);
        private void chatrcd_rtb_TextChanged(object sender, EventArgs e)
        {
            chatrcd_rtb.ScrollToCaret();
            if (this.WindowState == FormWindowState.Minimized)
            {
                FlashWindow(this.Handle, true);
            }
        }

        /// <summary>
        /// 当窗口恢复后取消任务栏的闪烁效果
        /// 当窗口最小化时判断是否要隐藏到系统托盘
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chat_frm_SizeChanged(object sender, EventArgs e)
        {
            switch (this.WindowState)
            {
                case FormWindowState.Normal:
                    FlashWindow(this.Handle, false);
                    break;
                case FormWindowState.Minimized:
                    if (_hideFlag)
                    {
                        notifyIcon1.Visible = true;
                        this.Visible = false;
                    }
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 在线列表下拉框显示之前向服务器发送请求在线列表的命令
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void online_cb_DropDown(object sender, EventArgs e)
        {
            _nws.Write(new byte[] { 0, 2 }, 0, 2);
        }

        /// <summary>
        /// 聊天模式改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void broadcast_rb_CheckedChanged(object sender, EventArgs e)
        {
            if (private_rb.Checked)
            {
                online_cb.Enabled = true;
            }
            else
            {
                online_cb.Enabled = false;
            }
        }

        /// <summary>
        /// 设置最小化到系统托盘的标记值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hide_cb_CheckedChanged(object sender, EventArgs e)
        {
            _hideFlag = hide_cb.Checked;
        }

        /// <summary>
        /// 产生闪屏振动效果
        /// </summary>
        private void Nudge()
        {
            if (notifyIcon1.Visible == true)
            {
                return;
            }
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.WindowState = FormWindowState.Normal;
            }
            int i = 0;
            Point _old = this.Location;
            Point _new1 = new Point(_old.X + 2, _old.Y + 2);
            Point _new2 = new Point(_old.X - 2, _old.Y - 2);
            _sp2.Play();
            while (i < 4)
            {
                this.Location = _new1;
                Thread.Sleep(60);
                this.Location = _new2;
                Thread.Sleep(60);
                i++;
            }
            this.Location = _old;
        }

        /// <summary>
        /// 发送闪屏振动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void nudge_pb_Click(object sender, EventArgs e)
        {
            string displayTxt = null;
            if (private_rb.Checked && online_cb.Text == string.Empty)
            {
                MessageBox.Show("非聊天室模式下必须先选择一个接收者!",
                                "发送闪屏振动",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);
                return;
            }
            if (private_rb.Checked)
            {
                _nws.Write(new byte[] { 0, 4 }, 0, 2);
                string _receiver = online_cb.Text;
                _nws.Write(Encoding.Unicode.GetBytes(_receiver), 0, Encoding.Unicode.GetBytes(_receiver).Length);
                displayTxt = string.Format("[系统提示]您向 {0} 发送了一个闪屏振动。/r/n/r/n", _receiver);
            }
            else
            {
                _nws.Write(new byte[] { 0, 3 }, 0, 2);
                displayTxt = "[系统提示]您向所有人发送了一个闪屏振动。/r/n/r/n";
            }
            chatrcd_rtb.AppendText(displayTxt);
            Nudge();
        }

        /// <summary>
        /// 以下是系统托盘菜单的处理函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void close_tsmi_Click(object sender, EventArgs e)
        {
            close_btn_Click(sender, e);
        }
        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            comeback_tsmi_Click(sender, e);
        }
        private void comeback_tsmi_Click(object sender, EventArgs e)
        {
            notifyIcon1.Visible = false;
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
            this.BringToFront();
        }

        #endregion

        //private void msg_tb_KeyDown(object sender, KeyEventArgs e)
        //{
        //    if (e.KeyCode == Keys.Control && e.KeyValue == 13)
        //    {
        //        send_btn.Click += new EventHandler(send_btn_Click);
        //        send_btn_Click(sender, e);
        //    }

        //}

        private void msg_tb_KeyPress(object sender, KeyPressEventArgs e)
        {

        }
    }
}

原创粉丝点击