黑马程序员--套接之局域网聊天服务端(待续)

 ------- Windows Phone 7手机开发.Net培训、期待与您交流! -------

服务端代码如下:

public FChatSever()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;//关闭微软对文本框的跨线程操作检查
        }


        Thread threadWatch = null;//负责监控听客户端连接请求的线程
        Socket socketWatch = null;//负责监听的套接字


        private void btnBeginListen_Click(object sender, EventArgs e)
        {
                   //------------------创建负责监听的套接字,参数(寻址协议,流连接,tcp协议)
            socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                   //------------------获得文本框里的IP地址对象
            IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
                   //---------创建包含IP和Port的网络节点对象
            IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text.Trim()));
                   //------将负责监听的套接字绑定到唯一的IP和端口上
            socketWatch.Bind(endpoint);
                   // -----设置监听的长度 
            socketWatch.Listen(10);
                   //----------线程实例化
            threadWatch = new Thread(WatchConnecting);
            threadWatch.IsBackground = true;  //设置为后台进程
            threadWatch.Start();
            ShowMsg("服务器启动监听成功");
            //  开始监听(执行代码,放入线程中处理了)
            //Socket sokconnection = socketWatch.Accept();
            //ShowMsg("客户端连接成功");
        }
        /// <summary>
        /// 监听客户端请求的方法
        /// </summary>
             //保存了服务器端  所有负责和客户端通信的套接字
        Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
              //保存了服务器端  所有负责调用通信套接字 .Recive的线程
        Dictionary<string ,Thread>dictThread=new Dictionary<string,Thread>();
        
        void WatchConnecting()
        {
            while (true)//持续不断的监听客户端请求
            {
                
                // 开始监听客户端请求,注意:accept 方法,会阻断当前的线程 
               Socket  sokconnection = socketWatch.Accept();
                //向列表控件中追加一个客户端的Ip端口字符串,作为客户端的唯一标识。
               lbOnline.Items.Add(sokconnection.RemoteEndPoint.ToString());
                //将与刻画段通信的套接字对象sokconnection添加到键值对集合中,并以客户端IP端口作为键。
               dict.Add(sokconnection.RemoteEndPoint.ToString(), sokconnection);
                   //创建通信线程
               Thread thr = new Thread(RecMsg);
               thr.IsBackground = true;
               thr.Start(sokconnection);
                dictThread.Add(sokconnection.RemoteEndPoint.ToString(),thr);


                ShowMsg("客户端连接成功"+sokconnection.RemoteEndPoint.ToString());
            }
        }


            //服务端用来监听客户端发送过来数据的方法
        void RecMsg(object socketClinetPara)
        {
            Socket socketClinet = socketClinetPara as Socket;
            while (true)
            {   //定义一个接受用的缓存区、(2M)
                byte[] arrMsgRec = new byte[1024 * 1024 * 2];
                // 将接收到的数据存入arrMsgRec数组中
                int length = -1;


                try
                {
                    length = socketClinet.Receive(arrMsgRec);
                }
                catch (SocketException ex)
                {
                    ShowMsg("异常:" + ex.Message);
                        //从通信套接字 集合中 删除被中断连接的 通信套接字对象
                    dict.Remove(socketClinet.RemoteEndPoint.ToString());
                        //从通信线程中删除被中断连接的 通信线程对象
                    dictThread.Remove(socketClinet.RemoteEndPoint.ToString());
                         //从列表中移除被中断的ip:Port
                    lbOnline.Items.Remove(socketClinet.RemoteEndPoint.ToString());
                    break;
                }
                if (arrMsgRec[0] == 0)//如果是0,则是消息。
                {
                    //此时是将数组所有的元素都转化成字符串,而真正接受的只有几个字符而已。
                    string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,1 , length-1);
                    ShowMsg(strMsgRec);
                }
                else if(arrMsgRec[0]==1)//是1,则发送的是文件数据。。
                {
                    SaveFileDialog sfd = new SaveFileDialog();//保存文件选择框对象
                             //用户选择文件路径
                    if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {   //获得要保存的文件路径
                        string fileSavePath = sfd.FileName;
                        //创建文件流,然后让文件流来根据路径创建一个文件
                        using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
                        {
                            fs.Write(arrMsgRec, 1, length-1);
                            ShowMsg("文件保存成功" + fileSavePath);
                        }


                    }
                };
            }
        }


        void ShowMsg(string msg)
        {
            txtMsg.AppendText(msg + "\r\n");
        }


        //发送消息到客户端
        private void btnSend_Click(object  sender, EventArgs e)
        {   
            if(string.IsNullOrEmpty(lbOnline.Text))
            {
                MessageBox.Show("请选择要发送的用户!");
            }
            else
            {
            string strMsg = txtMsgSend.Text.Trim();
            //将要发送的字符串转成UTF8对应的字节数组。
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
            //获得选中列表中选中的KEY
            string strClientKey = lbOnline.Text;
            //通过KEY,找到字典中对应的与某个客户端通信的套接字send方法,发送数据给对方。


            try
            {
                dict[strClientKey].Send(arrMsg);
                //sokconnection.Send(arrMsg); 
                ShowMsg("发送了数据出去" + strMsg);
            }
            catch (SocketException ex)
            {


                ShowMsg("发送时异常" + ex.Message);
            }
            catch (Exception ex)
            {


                ShowMsg("发送时异常" + ex.Message);
            }
            }
        }


        private void btnSendToAll_Click(object sender, EventArgs e)
        {
            string strMsg = txtMsgSend.Text.Trim();
            //将要发送的字符串转成UTF8对应的字节数组。
            byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
            foreach (Socket s in dict.Values)
            {
                s.Send(arrMsg);
            }
            ShowMsg("群发完毕+ :)");
        }


        private void FChatSever_Load(object sender, EventArgs e)
        {


        }
    }






















 ------- Windows Phone 7手机开发.Net培训、期待与您交流! -------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值