写着玩的聊天程序,拿出来给没有接触过的玩

it2022-05-05  113

写着玩的聊天程序,拿出来给没有接触过的玩

主要就是多线程与Socket的知识,注释写的还算详细,还是实际点帖全部代码吧。Client:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Threading;using System.Net;using System.Net.Sockets;

namespace TestClient{    public partial class Chat : Form    {        //以下是客户端到服务器端的消息开头        const string LOGININ  = "10"   ;//请求登陆的消息|||消息形式:10+自己的用户名        const string LOGINOUT  = "11"  ;//请求登出的消息|||消息形式:11+自己的用户名        const string GETULIST  = "12"  ;//请求获得在线用户列表|||消息形式:12+自己的用户名        const string P2PCONN  = "13"   ;//请求P2P连接的消息|||消息形式:13+自己的用户名+对方的用户名        const string HOLDLINE = "14";//保持连接.|||消息开式:14+自己的用户名        const string LOGINADD = "15";//新用户登录        const string LOGINREMOVE = "16";//用户登出        //以下是服务器到客户端的消息开头        const string HVUSER = "20";//用户名已存在        const string GETUSER = "21";//在线用户列表|||消息格式:21+用户名+EP        const string MAKHOLD = "22";//打洞命令|||消息格式:22+IP        const string LOGINOK = "23";//登陆成功        const string SERVCLS = "24";//服务器关闭        const string MSGEND = "25";//'消息结束          const string CHATMSGALL = "26";//发送给所有人        //以下是客户端到客户端的消息开头        const string HOLDOK = "30"    ;//打洞成功        const string CHATMSG = "31"   ;//聊天消息        const string CHTMSGEND = "32" ;//聊天消息发送成功

        private string userName;        public string UserName        {            private get { return userName; }            set { userName = value; }        }        private IPEndPoint serverEP;        public IPEndPoint ServerEP        {            set            {                serverEP = value;            }            private get            {                return serverEP;            }        }

        Socket clientSocket;        public Socket ClientSocket        {            private get { return clientSocket; }            set { clientSocket = value; }        }

        int getUrecCount;

        //和服务器保持连接连接时用到的byte数组        byte[] holdBytes;        List<string> OLUserName;        List<IPEndPoint> OLUserEP;        //为保持在线状态弄得        TimerCallback timerDelegate;        bool msgSendEnd = false;//消息是否发送成功,若发送成功,则会返回结束消息        private ManualResetEvent getUDone;//用来阻塞请求好友名单的线程,等待接收好友名单        private ManualResetEvent chatDone;//用来阻塞发送聊天消息时的线程                private ManualResetEvent holdDone;//用来阻塞打洞时的线程                private ManualResetEvent sendDone ;//用来阴塞发送消息的线程.等待收到回送的确认消息

        //监听的线程        Thread thListen;                delegate void myMethodDelegate(ref byte[] myInData);//登陆时用的事件        delegate void TextChangedMelegate(string text);//给textbox1赋值用到的委托        delegate void ComboboxBindDelegate();//用户绑定combobox的委托

        static bool testHold = false;        static bool testChat = false;        //用户列表的数据源        DataTable dt;        //上一条消息        string lastMsg = "";

        public Chat()        {            InitializeComponent();        }

        private void Chat_Load(object sender, EventArgs e)        {            Login login = new Login();            login.StartPosition = FormStartPosition.CenterParent;            login.Tag = this;            login.ShowDialog();               thListen = new Thread(new ThreadStart(this.Listen));            thListen.IsBackground = true;            thListen.Start();        }

        public void LoadInit()        {                        //timerDelegate = new TimerCallback(Holdonline);            //holdBytes = Encoding.Unicode.GetBytes(HOLDLINE + UserName);            登陆成功后.用一个timer,每隔50秒向服务器发送消息,保持在线状态跟在主机注册的端口            //System.Threading.Timer timer = new System.Threading.Timer(timerDelegate, null, 10000, 10000);            //登陆成功后.用一个timer,每隔50秒向服务器发送消息,保持在线状态跟在主机注册的端口            System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();            timer.Tick += new EventHandler(Holdonline);            timer.Interval = 50000;            timer.Start();

            //请求在线名单            this.Text = "正在获取在线名单,请稍后....";            bool getUbool = false;            //while (getUbool == false)            //{            //    //getUbool = GetU();            //    //if (getUbool == false)            //    //{            //    //    if (MessageBox.Show("是否重试?", "是否重试", MessageBoxButtons.YesNo) == DialogResult.Yes)            //    //    {            //    //        getUbool = false;            //    //    }            //    //    else            //    //    {            //    //        getUbool = true;            //    //    }            //    //}            //}        }

        private bool GetU()        {            getUDone = new ManualResetEvent(false);            byte[] getUbytes = Encoding.Unicode.GetBytes(GETULIST);            ClientSocket.SendTo(getUbytes, ServerEP);            byte[] data = new byte[4056];            string comStr = Encoding.Unicode.GetString(data, 0, 4);            myMethodDelegate GUrecv = new myMethodDelegate(RecvGetU);            GUrecv.BeginInvoke(ref data, null, null);            getUDone.WaitOne(30000, true);            string recvStr = Encoding.Unicode.GetString(data, 0, 4);            if (recvStr == comStr)            {                MessageBox.Show("服务器超时.或取好友名单失败!!");                return false;            }            string test = Encoding.Unicode.GetString(data);            if (Encoding.Unicode.GetString(data, 0, 4) == GETUSER)            {                GetUserList(data, getUrecCount);                this.comboBox1.Invoke(new ComboboxBindDelegate(ShowUserList));                //ShowUserList();                return true;            }            else            {                MessageBox.Show("服务器未知错误,获取在线名单失败!!");                return false;            }        }

        /// <summary>        /// 显示在线用户        /// </summary>        private void ShowUserList()        {            lock (OLUserName)            {                dt = new DataTable();                dt.Columns.Add("Name");                dt.Columns.Add("IP");                DataRow dr1 = dt.NewRow();                dr1["Name"] = "所有人";                dt.Rows.Add(dr1);                this.comboBox1.DataSource = dt;                this.comboBox1.ValueMember = "IP";                this.comboBox1.DisplayMember = "Name";                for (int i = 0; i < OLUserName.Count; i++)                {                    if (OLUserName[i] != "")                    {                        DataRow dr = dt.NewRow();                        dr["Name"] = OLUserName[i];                        dr["IP"] = OLUserEP[i];                        dt.Rows.Add(dr);                    }                }            }        }

        /// <summary>        /// 处理收到的在线用户信息        /// </summary>        /// <param name="userInfobytes"></param>        /// <param name="reccount"></param>        private void GetUserList(byte[] userInfobytes, int reccount)        {            string ustr = Encoding.Unicode.GetString(userInfobytes, 4, reccount - 4);

            string[] splitStr = null;            splitStr = ustr.Split('|');            string[] IPEPSplit = null;            OLUserName = new List<string>();            OLUserEP = new List<IPEndPoint>();            int i = 0;            for(int k=0;k<splitStr.Length -2;k = k+2)            {                OLUserName.Add(splitStr[k]);                IPEPSplit = splitStr[k + 1].Split(':');                OLUserEP.Add(new IPEndPoint(IPAddress.Parse(IPEPSplit[0]), Convert.ToInt32(IPEPSplit[1])));                IPEPSplit = null;                i++;            }        }

        //用保持在线状态的函数        private void Holdonline(object state,EventArgs e)        {            holdBytes = Encoding.Unicode.GetBytes(HOLDLINE + UserName);            ClientSocket.SendTo(holdBytes, ServerEP);        }

        //登陆时用来异步的接收服务器发送的消息        void RecvGetU(ref byte[] inData)        {            getUrecCount = ClientSocket.Receive(inData);            getUDone.Set();        }

        /// <summary>        /// 发送        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void buttonSend_Click(object sender, EventArgs e)        {            if (this.textBox2.Text.Trim() == "")                return;            else            {                SendChatMsg(this.comboBox1.Text, this.textBox2.Text);            }        }

        /// <summary>        /// 发送聊天消息        /// </summary>        /// <param name="remoteUser"></param>        /// <param name="chatMsgStr"></param>        private void SendChatMsg(string remoteUser, string chatMsgStr)        {            if (lastMsg.Trim() == chatMsgStr.Trim())            {                MessageBox.Show("看你傻样,还想刷屏!");                return;            }            else                lastMsg = chatMsgStr;            IPEndPoint remoteUEP = null;            if (remoteUser == "所有人")            {                for(int i=0;i<OLUserName.Count;i++)                {                    if (OLUserName[i].ToUpper().Trim() == this.UserName.ToUpper().Trim())                        continue;                    byte[] msgbytes = Encoding.Unicode.GetBytes(CHATMSGALL + UserName + "|" + chatMsgStr);                                        string test = OLUserEP[i].Address.ToString();                    string port = OLUserEP[i].Port.ToString();                    ClientSocket.SendTo(msgbytes, OLUserEP[i]);                                    }                this.textbox.AppendText(this.UserName + " to " + this.comboBox1.Text + ":" + chatMsgStr + "\n");                this.textbox.Focus();                Application.DoEvents();                this.textBox2.Focus();            }            else            {                for (int i = 0; i < OLUserName.Count; i++)                {                    if (remoteUser == OLUserName[i])                        remoteUEP = OLUserEP[i];                }                byte[] msgbytes = Encoding.Unicode.GetBytes(CHATMSG + userName + "|" + chatMsgStr);                byte[] holdbytes = Encoding.Unicode.GetBytes(P2PCONN + userName + "|" + remoteUser);                chatDone = new ManualResetEvent(false);                string test = remoteUEP.Address.ToString();                string port = remoteUEP.Port.ToString();                ClientSocket.SendTo(msgbytes, remoteUEP);                chatDone.WaitOne(1000, true);                this.textbox.AppendText(this.UserName + " to " + this.comboBox1.Text + ":" + chatMsgStr + "\n");                //this.textbox.Focus();                Application.DoEvents();                //this.textBox2.Focus();

                if (testChat)                {                    testChat = false;                    return;                }                testHold = false;                while (testHold == false)                {                    //开始打洞                    holdDone = new ManualResetEvent(false);                    ClientSocket.SendTo(holdbytes, remoteUEP);                    ClientSocket.SendTo(holdbytes, ServerEP);                    holdDone.WaitOne(1000, true);                    if (testHold == false)                    {                        //打洞超时                        testHold = true;                    }                    else                    {                        //打洞成功                                        }                }                while (testChat == false)                {                    //打洞成功准备发送                    chatDone = new ManualResetEvent(false);

                    ClientSocket.SendTo(msgbytes, remoteUEP);                    chatDone.WaitOne(1000, true);                    if (testChat == false)                    {                        //发送超时                        testChat = true;                    }                    else                    {                        //发送成功                        testChat = true;                    }                }            }            this.textBox2.Text = "";            testHold = false;            testChat = false;        }       

        /// <summary>        /// 客户程序监听的函数        /// </summary>        private void Listen()        {            while (true)            {                try                {                    int recv = 0;//收到的字节数                    byte[] data = new byte[1024];//缓冲区大小                    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);                    EndPoint tempRemoteEP = (EndPoint)sender;                                        recv = ClientSocket.ReceiveFrom(data, ref tempRemoteEP);                    //获得消息头的内容                    string msgHead = Encoding.Unicode.GetString(data, 0, 4);                    switch (msgHead)                    {                                                   case MSGEND:                            msgSendEnd = true;                            sendDone.Set();                            break;                        case LOGININ:                            AddOnLine(data, recv);                            break;                        case LOGINOUT:                            RemoveOnLine(data, recv);                            break;                        case MAKHOLD:                            MakeHold(data, recv);                            break;                        case CHATMSG:                            ShowChatMsg(data, recv);                            break;                        case CHATMSGALL:                            ShowChatMsgAll(data, recv);                            break;                        case HOLDOK:                            testHold = true;                            holdDone.Set();                            break;                        case CHTMSGEND:                            testChat = true;                            chatDone.Set();                            break;                        case LOGINADD:                            this.GetU();                            break;                        case LOGINREMOVE:                            this.GetU();                            break;                    }                }                catch                { }            }        }

        /// <summary>        /// 处理聊天消息        /// </summary>        /// <param name="data"></param>        /// <param name="recv"></param>        private void ShowChatMsgAll(byte[] data, int recv)        {            string msgStr = Encoding.Unicode.GetString(data, 4, recv - 4);            string[] splitStr = msgStr.Split('|');            string fromUname = splitStr[0];            string msg = splitStr[1];            this.textbox.Invoke(new TextChangedMelegate(SetTextBox), fromUname + " to 所有人:" + msg);                    }

        /// <summary>        /// 处理聊天消息        /// </summary>        /// <param name="data"></param>        /// <param name="recv"></param>        private void ShowChatMsg(byte[] data, int recv)        {            string msgStr = Encoding.Unicode.GetString(data, 4, recv-4);            string[] splitStr = msgStr.Split('|');            string fromUname = splitStr[0];            string msg = splitStr[1];            this.textbox.Invoke(new TextChangedMelegate(SetTextBox), fromUname + " to " + userName + ":" + msg);            //this.textBox1.Text += fromUname + " to " + userName + ":" + msg + "\n";            byte[] tempbytes = Encoding.Unicode.GetBytes(CHTMSGEND);            for (int i = 0; i < OLUserName.Count; i++)            {                if (OLUserName[i].ToUpper() == fromUname.ToUpper())                {                    ClientSocket.SendTo(tempbytes, OLUserEP[i]);                }            }        }

        private void SetTextBox(string text)        {            this.textbox.SelectionColor = Color.Blue;            this.textbox.AppendText(text + "\n");            //this.textbox.Focus();            Application.DoEvents();            //this.textBox2.Focus();        }

        /// <summary>        /// 处理打洞函数        /// </summary>        /// <param name="data"></param>        /// <param name="recv"></param>        private void MakeHold(byte[] indata, int recvcount)        {            string makholdstr = Encoding.Unicode.GetString(indata, 4, recvcount);            string[] ipepstr = makholdstr.Split(':');            IPEndPoint holdEP = new IPEndPoint(IPAddress.Parse(ipepstr[0]), Convert.ToInt32(ipepstr[1]));            byte[] holdbytes = Encoding.Unicode.GetBytes(HOLDOK + UserName);                        //回送打洞消息            ClientSocket.SendTo(holdbytes, holdEP);        }

        /// <summary>        /// 处理用户上线的函数        /// </summary>        private void AddOnLine(byte[] inData, int recvCount)        {            string inStr = Encoding.Unicode.GetString(inData, 4, recvCount - 4);            string[] userinfo = inStr.Split('|');            string[] strUserEP = userinfo[1].Split(':');            int count = OLUserName.Count - 1;            //for (int i = 0; i < count; i++)            //{            //    if (OLUserName[i] == "")            //    {            OLUserName.Add(userinfo[0]);            IPEndPoint ip = new IPEndPoint(IPAddress.Parse(strUserEP[0]), Convert.ToInt32(strUserEP[1]));            OLUserEP.Add(ip);            lock (dt)            {                DataRow dr = this.dt.NewRow();                dr["Name"] = userinfo[0];                dr["IP"] = ip;                dt.Rows.Add(dr);            }            this.textbox.Invoke(new TextChangedMelegate(SetTextBox), userinfo[0] + "上线了!");                        //this.textBox1.Text += userinfo[0] + "上线了!\n";            //break;            //    }            //}        }

        /// <summary>        /// 处理用户下线的函数        /// </summary>        private void RemoveOnLine(byte[] inData,int recvCount)        {            string offUname = Encoding.Unicode.GetString(inData,4,recvCount-4);            for(int i = 0; i< OLUserName.Count-1;i++)            {                if(OLUserName[i] == offUname)                {                    OLUserName.Remove(offUname);                    OLUserEP.RemoveAt(i);                    lock (dt)                    {                        foreach (DataRow dr in dt.Rows)                        {                            if (dr["name"].ToString().Trim() == offUname.Trim())                            {                                dt.Rows.Remove(dr);                                break;                            }                        }                    }                    this.textbox.Invoke(new TextChangedMelegate(SetTextBox), offUname + "下线了!");                    //this.textBox1.Text += offUname + "下线了!\n";                    break;                }            }        }

        private void textBox2_KeyPress(object sender, KeyPressEventArgs e)        {            if (e.KeyChar == '\r')                this.buttonSend_Click(null, null);        }

        private void textbox_TextChanged(object sender, EventArgs e)        {            让文本框获取焦点               //this.textbox.Focus();            设置光标的位置到文本尾               //this.textbox.Select(this.richTextBoxInfo.TextLength, 0);            滚动到控件光标处               //this.textbox.ScrollToCaret();        }

        private void Chat_FormClosed(object sender, FormClosedEventArgs e)        {            this.thListen.Abort();            string loginOutStr = LOGINOUT + UserName;            byte[] sendBytes = Encoding.Unicode.GetBytes(loginOutStr);            ClientSocket.SendTo(sendBytes,ServerEP);        }    }}namespace TestClient{    partial class Chat    {        /// <summary>        /// 必需的设计器变量。        /// </summary>        private System.ComponentModel.IContainer components = null;

        /// <summary>        /// 清理所有正在使用的资源。        /// </summary>        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>        protected override void Dispose(bool disposing)        {            if (disposing && (components != null))            {                components.Dispose();            }            base.Dispose(disposing);        }

        #region Windows 窗体设计器生成的代码

        /// <summary>        /// 设计器支持所需的方法 - 不要        /// 使用代码编辑器修改此方法的内容。        /// </summary>        private void InitializeComponent()        {            this.panel1 = new System.Windows.Forms.Panel();            this.buttonSend = new System.Windows.Forms.Button();            this.textBox2 = new System.Windows.Forms.TextBox();            this.label1 = new System.Windows.Forms.Label();            this.comboBox1 = new System.Windows.Forms.ComboBox();            this.textbox = new System.Windows.Forms.RichTextBox();            this.panel1.SuspendLayout();            this.SuspendLayout();            //             // panel1            //             this.panel1.Controls.Add(this.buttonSend);            this.panel1.Controls.Add(this.textBox2);            this.panel1.Controls.Add(this.label1);            this.panel1.Controls.Add(this.comboBox1);            this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;            this.panel1.Location = new System.Drawing.Point(0, 382);            this.panel1.Name = "panel1";            this.panel1.Size = new System.Drawing.Size(557, 59);            this.panel1.TabIndex = 0;            //             // buttonSend            //             this.buttonSend.Location = new System.Drawing.Point(470, 29);            this.buttonSend.Name = "buttonSend";            this.buttonSend.Size = new System.Drawing.Size(75, 23);            this.buttonSend.TabIndex = 1;            this.buttonSend.Text = "发送";            this.buttonSend.UseVisualStyleBackColor = true;            this.buttonSend.Click += new System.EventHandler(this.buttonSend_Click);            //             // textBox2            //             this.textBox2.Location = new System.Drawing.Point(3, 29);            this.textBox2.Name = "textBox2";            this.textBox2.Size = new System.Drawing.Size(443, 21);            this.textBox2.TabIndex = 0;            this.textBox2.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox2_KeyPress);            //             // label1            //             this.label1.AutoSize = true;            this.label1.Location = new System.Drawing.Point(3, 6);            this.label1.Name = "label1";            this.label1.Size = new System.Drawing.Size(53, 12);            this.label1.TabIndex = 2;            this.label1.Text = "发送给:";            //             // comboBox1            //             this.comboBox1.FormattingEnabled = true;            this.comboBox1.Location = new System.Drawing.Point(62, 3);            this.comboBox1.Name = "comboBox1";            this.comboBox1.Size = new System.Drawing.Size(121, 20);            this.comboBox1.TabIndex = 3;            //             // textbox            //             this.textbox.BackColor = System.Drawing.SystemColors.ActiveCaptionText;            this.textbox.Dock = System.Windows.Forms.DockStyle.Fill;            this.textbox.Location = new System.Drawing.Point(0, 0);            this.textbox.Name = "textbox";            this.textbox.ReadOnly = true;            this.textbox.Size = new System.Drawing.Size(557, 382);            this.textbox.TabIndex = 1;            this.textbox.Text = "";            this.textbox.TextChanged += new System.EventHandler(this.textbox_TextChanged);            //             // Chat            //             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;            this.ClientSize = new System.Drawing.Size(557, 441);            this.Controls.Add(this.textbox);            this.Controls.Add(this.panel1);            this.Name = "Chat";            this.Text = "Chat";            this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Chat_FormClosed);            this.Load += new System.EventHandler(this.Chat_Load);            this.panel1.ResumeLayout(false);            this.panel1.PerformLayout();            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Panel panel1;        private System.Windows.Forms.TextBox textBox2;        private System.Windows.Forms.Label label1;        private System.Windows.Forms.ComboBox comboBox1;        private System.Windows.Forms.Button buttonSend;        private System.Windows.Forms.RichTextBox textbox;    }}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;

namespace TestClient{    public partial class Login : Form    {        //以下是客户端到服务器端的消息开头        const string LOGININ = "10";//请求登陆的消息|||消息形式:10+自己的用户名        const string LOGINOK = "23";//登陆成功        //以下是服务器到客户端的消息开头        const string HVUSER  = "20";//用户名已存在

        Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);  //客户端套节字的定义        IPEndPoint serverEP;//服务器的IPEP

        delegate void myMethodDelegate(ref byte[] myInData);//登陆时用的事件

        private ManualResetEvent receiveDone;//在登陆时用来阻塞线程,等待收到数据

        bool inPutOk = false;        public Login()        {            InitializeComponent();        }

        private void button1_Click(object sender, EventArgs e)        {            try            {                serverEP = new IPEndPoint(IPAddress.Parse(this.textBoxServerIP.Text), 11000);                inPutOk = true;            }            catch            {                MessageBox.Show("你输入的服务器IP不正确,请重新输入.");                inPutOk = false;            }

                        //判断用户是否登陆成功            bool ok = false;            while (ok == false)            {                bool loginOk = LogOn(this.textBoxUserName.Text);                if (loginOk)                    ok = true;                else                {                    DialogResult res = MessageBox.Show("是否重试?", "是否重试", MessageBoxButtons.YesNo);                    if (res == DialogResult.No)                        ok = true;                    else                        ok = false;                }            }            Chat c = (Chat)this.Tag;            c.UserName = this.textBoxUserName.Text;            c.ServerEP = serverEP;            c.ClientSocket = clientSocket;            c.LoadInit();            this.Close();                  }

        //登陆函数        private bool LogOn(string username)        {            receiveDone = new ManualResetEvent(false);            byte[] userBytes = null;            bool userOk = false;            //判断用户名是否符合格式            while(userOk != true)            {            username = username.ToUpper();            userBytes = Encoding.Unicode.GetBytes(LOGININ + username);

            if(userBytes.Length > 24 || userBytes.Length < 10)            {                MessageBox.Show("用户名不得小于6个字节,且不得大于20个字节.");                return false;            }            else                userOk = true;            }

            //向服务器发送客户消息            clientSocket.SendTo(userBytes, serverEP);            byte[] data = new Byte[1024];            string comStr = Encoding.Unicode.GetString(data,0,4);       

            //异面的接收服务器回送的消息            myMethodDelegate DGrecv = new myMethodDelegate(RecvLogin);            DGrecv.BeginInvoke(ref data, null, null);

            //等待服务器回送消息的时长为10秒,否则为服务器超时            receiveDone.WaitOne(30000, true);

            string recvStr = Encoding.Unicode.GetString(data,0,4);            if(recvStr == comStr)            {                MessageBox.Show("服务器超时.登陆失败!!");                return false;            }            else            {                if(Encoding.Unicode.GetString(data,0,4) == LOGINOK)                {                    MessageBox.Show("登陆成功!!");                }                else                {                    if (Encoding.Unicode.GetString(data, 0, 4) == HVUSER)                    {                        MessageBox.Show("用户名重复.登陆失败!!");                        return false;                    }                    else                    {                        if (Encoding.Unicode.GetString(data, 0, 4) == LOGINOK)                        {                            MessageBox.Show("服务器未知错误,登陆失败!!!!");                            return false;                        }                                           }                }            }            return true;        }

        //登陆时用来异步的接收服务器发送的消息        void RecvLogin(ref byte[] inData)        {            clientSocket.Receive(inData);            receiveDone.Set();        }    }}namespace TestClient{    partial class Login    {        /// <summary>        /// 必需的设计器变量。        /// </summary>        private System.ComponentModel.IContainer components = null;

        /// <summary>        /// 清理所有正在使用的资源。        /// </summary>        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>        protected override void Dispose(bool disposing)        {            if (disposing && (components != null))            {                components.Dispose();            }            base.Dispose(disposing);        }

        #region Windows 窗体设计器生成的代码

        /// <summary>        /// 设计器支持所需的方法 - 不要        /// 使用代码编辑器修改此方法的内容。        /// </summary>        private void InitializeComponent()        {            this.label2 = new System.Windows.Forms.Label();            this.textBoxServerIP = new System.Windows.Forms.TextBox();            this.label1 = new System.Windows.Forms.Label();            this.textBoxUserName = new System.Windows.Forms.TextBox();            this.button1 = new System.Windows.Forms.Button();            this.SuspendLayout();            //             // label2            //             this.label2.AutoSize = true;            this.label2.Location = new System.Drawing.Point(56, 27);            this.label2.Name = "label2";            this.label2.Size = new System.Drawing.Size(77, 12);            this.label2.TabIndex = 7;            this.label2.Text = "服务器IP:";            //             // textBoxServerIP            //             this.textBoxServerIP.Location = new System.Drawing.Point(139, 24);            this.textBoxServerIP.Name = "textBoxServerIP";            this.textBoxServerIP.Size = new System.Drawing.Size(100, 21);            this.textBoxServerIP.TabIndex = 6;            this.textBoxServerIP.Text = "10.24.11.231";            //             // label1            //             this.label1.AutoSize = true;            this.label1.Location = new System.Drawing.Point(56, 68);            this.label1.Name = "label1";            this.label1.Size = new System.Drawing.Size(53, 12);            this.label1.TabIndex = 9;            this.label1.Text = "用户名:";            //             // textBoxUserName            //             this.textBoxUserName.Location = new System.Drawing.Point(139, 65);            this.textBoxUserName.Name = "textBoxUserName";            this.textBoxUserName.Size = new System.Drawing.Size(100, 21);            this.textBoxUserName.TabIndex = 8;            //             // button1            //             this.button1.Location = new System.Drawing.Point(100, 106);            this.button1.Name = "button1";            this.button1.Size = new System.Drawing.Size(75, 23);            this.button1.TabIndex = 10;            this.button1.Text = "登 陆";            this.button1.UseVisualStyleBackColor = true;            this.button1.Click += new System.EventHandler(this.button1_Click);            //             // Login            //             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;            this.ClientSize = new System.Drawing.Size(292, 144);            this.Controls.Add(this.button1);            this.Controls.Add(this.label1);            this.Controls.Add(this.textBoxUserName);            this.Controls.Add(this.label2);            this.Controls.Add(this.textBoxServerIP);            this.Name = "Login";            this.Text = "Login";            this.ResumeLayout(false);            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Label label2;        private System.Windows.Forms.TextBox textBoxServerIP;        private System.Windows.Forms.Label label1;        private System.Windows.Forms.TextBox textBoxUserName;        private System.Windows.Forms.Button button1;    }}Server:using System;using System.Drawing;using System.Collections;using System.Collections.Generic;using System.ComponentModel;using System.Windows.Forms;using System.Data;using System.Net.Sockets;using System.Threading;using System.Net;using System.Text;

namespace ChatServer{ /// <summary> /// Form1 的摘要说明。 /// </summary> public partial class Form1 : System.Windows.Forms.Form {  /// <summary>  /// 必需的设计器变量。  /// </summary>  private System.ComponentModel.Container components = null;  //全局变量  Socket ServerSocket = null;  IPEndPoint ipep = null;  Hashtable htUserList = null;  string[] userName = new string[1000];  IPEndPoint[] userIPEP = new IPEndPoint[1000];  int[] userTime = new int[1000];  TimerCallback timerDelegate = null;  WriteLog writeLog = null;  Thread listenTH = null;  bool flag = true;

  //常量  //以下是客户端到服务器端的消息开头  const string LOGININ = "10"; //请求登陆的消息|||消息形式:10+自己的用户名  const string LOGINOUT = "11"; //请求登出的消息|||消息形式:11+自己的用户名  const string GETULIST = "12"; //请求获得在线用户列表|||消息形式:12  const string P2PCONN = "13"; //请求P2P连接的消息|||消息形式:13+自己的用户名+|+对方的用户名  const string HOLDLINE = "14"; //保持连接.|||消息开式:14+自己的用户名        const string LOGINADD = "15";//新用户登录        const string LOGINREMOVE = "16";//用户登出

  //以下是服务器到客户端的消息开头  const string HVUSER = "20"; //用户名已存在  const string GETUSER = "21"; //在线用户列表|||消息格式:21+用户名+EP  const string MAKHOLD = "22"; //打洞命令|||消息格式:22+IP  const string LOGINOK = "23"; //登陆成功  const string SERVCLS = "24"; //服务器关闭  const string MSGEND = "25"; //消息结束

  //以下是服务器端的命名  const string EXITPRO = "EXIT"; //退出命令  const string SHOWULIST = "SHOWUSER";  private System.Windows.Forms.StatusBar statusBar1;  private System.Windows.Forms.StatusBarPanel statusBarPanel1;  private System.Windows.Forms.TextBox textBox1; //显示在线用户  const string HELP = "HELP"; //显示帮助        private List<IPEndPoint> onlineIPList;

  public Form1()  {   //   // Windows 窗体设计器支持所必需的   //   InitializeComponent();

   //初始化变量   ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);    ipep = new IPEndPoint(IPAddress.Any, 11000);   htUserList = new Hashtable();   writeLog = new WriteLog();   timerDelegate = new TimerCallback(OnLineTimeOut);  }

  /// <summary>  /// 清理所有正在使用的资源。  /// </summary>  protected override void Dispose( bool disposing )  {   if( disposing )   {    if (components != null)     {     components.Dispose();    }   }   base.Dispose( disposing );  }

  #region Windows 窗体设计器生成的代码  /// <summary>  /// 设计器支持所需的方法 - 不要使用代码编辑器修改  /// 此方法的内容。  /// </summary>  private void InitializeComponent()  {   this.statusBar1 = new System.Windows.Forms.StatusBar();   this.statusBarPanel1 = new System.Windows.Forms.StatusBarPanel();   this.textBox1 = new System.Windows.Forms.TextBox();   ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).BeginInit();   this.SuspendLayout();   //    // statusBar1   //    this.statusBar1.Location = new System.Drawing.Point(0, 319);   this.statusBar1.Name = "statusBar1";   this.statusBar1.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {                        this.statusBarPanel1});   this.statusBar1.ShowPanels = true;   this.statusBar1.Size = new System.Drawing.Size(466, 22);   this.statusBar1.TabIndex = 0;   //    // statusBarPanel1   //    this.statusBarPanel1.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring;   this.statusBarPanel1.Text = "statusBarPanel1";   this.statusBarPanel1.Width = 450;   //    // textBox1   //    this.textBox1.Dock = System.Windows.Forms.DockStyle.Left;   this.textBox1.Location = new System.Drawing.Point(0, 0);   this.textBox1.Multiline = true;   this.textBox1.Name = "textBox1";   this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;   this.textBox1.Size = new System.Drawing.Size(286, 319);   this.textBox1.TabIndex = 1;   this.textBox1.Text = "";   //    // Form1   //    this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);   this.ClientSize = new System.Drawing.Size(466, 341);   this.Controls.Add(this.textBox1);   this.Controls.Add(this.statusBar1);   this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;   this.MaximizeBox = false;   this.Name = "Form1";   this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;   this.Text = "服务程序";   this.Load += new System.EventHandler(this.Form1_Load);   this.Closed += new System.EventHandler(this.Form1_Closed);   ((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).EndInit();   this.ResumeLayout(false);

  }  #endregion

  /// <summary>  /// 启动服务器  /// </summary>  /// <param name="sender"></param>  /// <param name="e"></param>  private void Form1_Load(object sender, System.EventArgs e)  {   IPAddress[] addressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;   IPAddress ServerIP = addressList[0];   ServerSocket.Bind(ipep);   SetStatusText("服务器正在启动......");   SetStatusText("服务器IP:" + ServerIP.ToString() + "  正在监听" + ipep.Port.ToString() + "端口");   listenTH = new Thread(new ThreadStart(Listen)); //监听线程   listenTH.Start(); //启动   SetStatusText("服务器启动成功.....");   System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();   timer.Tick += new EventHandler(timer_Tick);   timer.Interval = 5000;   timer.Start();  }

  /// <summary>  /// 服务器监听函数  /// </summary>  private void Listen()  {   try   {    while (flag)    {     int recv = 0;     byte[] data = new byte[1024];     IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);     EndPoint tempRemoteEP = sender as EndPoint;     recv = ServerSocket.ReceiveFrom(data, ref tempRemoteEP);     string msgHead = Encoding.Unicode.GetString(data, 0, 4);     switch (msgHead)     {      case LOGININ: //用户登录       string LoginThing = UserLogin(data, (IPEndPoint)tempRemoteEP, recv);       if (LoginThing == HVUSER) //用户存在       {        SendMsg(HVUSER, (IPEndPoint)tempRemoteEP);       }       else       {           SendMsg(LOGINOK, (IPEndPoint)tempRemoteEP);                                if (onlineIPList == null)                                {                                    onlineIPList = new List<IPEndPoint>();                                }                                onlineIPList.Add((IPEndPoint)tempRemoteEP);                                foreach (IPEndPoint ip in onlineIPList)                                {                                    SendMsg(LOGINADD, ip);                                }       }       break;      case LOGINOUT: //用户退出       Userloginout(data, recv);                            onlineIPList.Remove((IPEndPoint)tempRemoteEP);                            foreach (IPEndPoint ip in onlineIPList)                            {                                SendMsg(LOGINREMOVE, ip);                            }       break;      case GETULIST: // 获取用户列表       string userInfor = GetUserList();       SendMsg(GETUSER + userInfor, (IPEndPoint)tempRemoteEP);       break;      case P2PCONN: //打洞       QuestP2PConn(data, recv);       break;      case HOLDLINE:       HoldOnLine(data, recv);       break;     }    }   }   catch (System.Exception errr)   {    writeLog.AppendErrorLog(errr.ToString());   }  }

  /// <summary>  /// 保持用户在线  /// </summary>  /// <param name="data"></param>  /// <param name="recvCount"></param>  private void HoldOnLine(byte[] data, int recvCount)  {   string Uname = Encoding.Unicode.GetString(data, 4, recvCount - 4);   int i = 0;   for (i=0;i<userName.Length;i++)   {    if (Uname == userName[i])    {     userTime[i] = 60;     break;    }   }  }

  /// <summary>  /// 用户超时退出  /// </summary>  private void OnLineTimeOut(object state)  {   int i = 0, j= 0;   for (i=0;i<userName.Length;i++)   {    if (userTime[i] > 0)    {     userTime[i] -= 5;     if (userTime[i] < 0)     {      string loginoutmsg = LOGINOUT + userName[i];      userName[i] = "";      userIPEP[i] = null;            byte[] ULoginOutbytes = Encoding.Unicode.GetBytes(loginoutmsg);      for (i=1;j<userName.Length;j++)      {       if (userName[j] != "")       {        if (userIPEP[j] != null)        {         ServerSocket.SendTo(ULoginOutbytes, userIPEP[j]);        }       }      }     }    }   }  }

  /// <summary>  /// 转发P2P连接请求  /// </summary>  private void QuestP2PConn(byte[] data, int recv)  {   string recvStr = Encoding.Unicode.GetString(data, 4, recv - 4);   string[] split = recvStr.Split(new char[]{'|'});   IPEndPoint fromEP = null, toEP = null;   int i;   for (i=0;i<userName.Length;i++)   {    if (userName[i] == split[0])    {     fromEP = userIPEP[i];    }    if (userName[i] == split[1])    {     toEP = userIPEP[i];    }   }   byte[] holdbyte = Encoding.Unicode.GetBytes(MAKHOLD + fromEP.ToString());   ServerSocket.SendTo(holdbyte, toEP);  }

  /// <summary>  /// 用户登录,直接返回登陆是否成功的值  /// </summary>  /// <param name="data"></param>  /// <param name="userEP"></param>  /// <param name="recvCount"></param>  /// <returns></returns>  private string UserLogin(byte[] data, IPEndPoint userEP, int recvCount)  {   string Uname = Encoding.Unicode.GetString(data, 4, recvCount - 4);   byte[] Uinfobytes = null;   int i, j;   for (i=0;i<userName.Length;i++)   {    if (userName[i] != "" && userName[i] != null)    {     if (userName[i].Equals(Uname))      return HVUSER;    }   }   for (i=0;i<userName.Length;i++)   {    if (userName[i] == "" || userName[i] == null)    {     userName[i] = Uname;     userIPEP[i] = userEP;     userTime[i] = 60;     Uinfobytes = Encoding.Unicode.GetBytes(LOGININ + userName[i] + "|" + userIPEP[i].ToString());     for (j=1;j<userName.Length;j++)     {      if (userName[j] != "" && userName[j] != Uname && userName[j] != null && userIPEP[j] != null)      {       ServerSocket.SendTo(Uinfobytes, userIPEP[j]);      }     }     break;    }   }   return LOGINOK;  }

  /// <summary>  /// 用户退出  /// </summary>  /// <param name="data"></param>  /// <param name="recvCount"></param>  private void Userloginout(byte[] data, int recvCount)  {   int i = 0, j = 0;   string Uname = Encoding.Unicode.GetString(data, 4, recvCount - 4);   for (i=0;i<userName.Length;i++)   {    if (Uname.ToUpper() == userName[i].ToUpper())    {     string loginOutMsg = LOGINOUT + Uname;     userName[i] = "";     userIPEP[i] = null;     userTime[i] = 0;     for (j=1;j<userName.Length;j++)     {      if (userName[j]!= null && userName[j] != "")      {       SendMsg(loginOutMsg, userIPEP[j]);      }     }     break;    }   }  }

  /// <summary>  /// 获取用户列表  /// </summary>  /// <returns></returns>  private string GetUserList()  {   string userInfor = "";   int i = 0;   for (i=0;i<userName.Length;i++)   {    if (userName[i] != "" && userName[i] != null && userIPEP[i] != null)    {     userInfor += userName[i] + "|" + userIPEP[i].ToString() + "|";    }   }   return userInfor;  }

  /// <summary>  /// 发送消息  /// </summary>  /// <param name="msg"></param>  /// <param name="remoteEP"></param>  private void SendMsg(string msg, IPEndPoint remoteEP)  {   byte[] sendBytes = Encoding.Unicode.GetBytes(msg);   try   {    ServerSocket.SendTo(sendBytes, remoteEP);   }   catch (System.Exception errr) {    writeLog.AppendErrorLog(errr.ToString());   }  }

  /// <summary>  /// 提示信息  /// </summary>  /// <param name="text"></param>  /// <returns></returns>  private void SetStatusText(string text)  {   this.statusBarPanel1.Text = text;  }

  /// <summary>  /// 显示在线用户   /// </summary>  private StringBuilder ShowUser()  {   StringBuilder strB = new StringBuilder();   if (userName != null && userName.Length > 0)   {    int i;    for (i=0;i<userName.Length;i++)    {     if (userName[i] != "" && userIPEP[i] != null)     {      strB.Append(Environment.NewLine + "用户名:" + userName[i] + "  地址:" + userIPEP[i].ToString());     }    }   }   return strB;  }

  /// <summary>  /// 退出  /// </summary>  /// <param name="sender"></param>  /// <param name="e"></param>  private void Form1_Closed(object sender, System.EventArgs e)  {   flag = false;   if (listenTH != null)   {    if (listenTH.ThreadState == ThreadState.Running)    {     listenTH.Abort();    }    listenTH = null;   }   timerDelegate = null;   ServerSocket.Close();  }

  private void timer_Tick(object sender, EventArgs e)  {   OnLineTimeOut(null);   StringBuilder strB = ShowUser();   this.textBox1.Text = strB.ToString();  }

 }}using System;using System.Text;using System.IO;using System.Windows.Forms;

namespace ChatServer{ /// <summary> /// WriteLog 的摘要说明。 /// </summary> public class WriteLog {  public WriteLog()  {   //   // TODO: 在此处添加构造函数逻辑   //  }  /// <summary>  /// 追加日志文件  /// </summary>  /// <param name="errorMsg"></param>  public void AppendErrorLog(string errorMsg)  {   try   {    StringBuilder strB = new StringBuilder();    strB.Append(DateTime.Now.ToString());    strB.Append("   ");    strB.Append(Environment.MachineName.ToString());    strB.Append("   ");    strB.Append(Environment.UserDomainName.ToString() + "\\" + Environment.UserName);    strB.Append("   ");    strB.Append(Environment.OSVersion.Platform.ToString() + "\\" + Environment.OSVersion.Version.ToString());    strB.Append(Environment.NewLine + Environment.NewLine);    strB.Append(errorMsg);    strB.Append(Environment.NewLine + Environment.NewLine);    AppendErrorLog(strB);   }   catch{}  }

  /// <summary>  /// 追加日志文件  /// </summary>  /// <param name="strB"></param>  public void AppendErrorLog(StringBuilder strB)  {   try   {    string filePath = "";    filePath = CreateErrorLogFile();    FileStream fileStream = File.Open(filePath, FileMode.Append, FileAccess.Write);    StreamWriter streamWriter = new StreamWriter(fileStream);        streamWriter.Write(strB.ToString());    streamWriter.Flush();    streamWriter.Close();    fileStream.Close();    fileStream = null;   }   catch{}  }

  /// <summary>  /// 创建日志文件  /// </summary>  private string CreateErrorLogFile()  {   string directoryPath = Application.StartupPath + "\\ErrorLog";   string filePath = string.Empty;   //判断日志文件夹是否存在   if (!Directory.Exists(directoryPath))   {    Directory.CreateDirectory(directoryPath);   }   //根据日期创建日志文件   filePath = directoryPath + "\\Error" + string.Format("{0:D2}", DateTime.Today.Year) + string.Format("{0:D2}", DateTime.Today.Month) + string.Format("{0:D2}", DateTime.Today.Day) + ".log";   if (!File.Exists(filePath))   {    FileStream fileStream = File.Create(filePath);    fileStream.Close();   }   return filePath;  }

 }}

 

posted on 2007-04-04 10:54 tianyamoon 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/tianyamoon/archive/2007/04/04/699414.html


最新回复(0)