黑马程序员--多线程与套接字组合:简单聊天室(1)

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

这个聊天室能够把多线程和套接字结合起来应用.

简单聊天室功能概述:

1.分为客户端和服务端

2.服务端能够显示在线列表和群发消息功能.

3.客户端可以向服务端发送文件和消息.

端口分配是,参考下面的端口介绍.

端口分为以下三类:
(1)公认端口(Well Known Ports):从0到1023,它们紧密绑定(binding)于一些服务。通常这些端口的通讯 明确表明了某种服务的协议。例如:80端口实际上总是HTTP通讯。
(2)注册端口(Registered Ports):从1024到49151。它们松散地绑定于一些服务。也就是说有许多服务绑定于 这些端口,这些端口同样用于许多其它目的。例如:许多系统处理动态端口从1024左右开始。
(3)动态和/或私有端口(Dynamic and/or Private Ports):从49152到65535。理论上,不应为服务分配这些端 口。实际上,机器通常从1024起分配动态端口。但也有例外:SUN的RPC端口从32768开
始。

界面的预览:

下面是客户端:




服务端:


下面介绍服务端的实现的核心代码:

服务的启动:

 //保存了服务器端 所有负责和客户端通信的套接字.
        Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
        //保存了服务器端所有负责调用 通信套接字.Receive方法的线程.
        Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();

        /// <summary>
        /// 监听客户端请求的方法
        /// </summary>
        void WatchConnction()
        {
            while (true)
            {
                //开始监听客户端连接请求,注意:Accept方法,会阻断当前线程
                Socket sokCconnection = socketWatch.Accept();//一旦监听到客户端的请求,就会返回一个负责和该客户端通信的套接字连接    
               
                //向列表控件中追加一个客户端的IP端字符串,做为客户端的一个唯一标识
                lboOnline.Items.Add(sokCconnection.RemoteEndPoint);

                //将与客户端通信的 套接字对象 sokCconnection,添加到键值集合中,并以客户端IP端口做为键值
                dict.Add(sokCconnection.RemoteEndPoint.ToString(), sokCconnection);

                //创建通信线程
               // ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMSG);
                Thread thr = new Thread(RecMSG);
                thr.IsBackground = true;
               // thr.SetApartmentState(ApartmentState.STA);
                thr.Start(sokCconnection);


                dictThread.Add(sokCconnection.RemoteEndPoint.ToString(), thr);


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

点击启动服务:

 //启动服务
        private void btnBeginLisgen_Click(object sender, EventArgs e)
        {
            //创建负责监听的套接字,参数(使用ipv4寻址协议,使用流式连接,使用TCP传输协议)
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //获取文本框中的IP地址对象.
            IPAddress address = IPAddress.Parse(txtIP.Text);
          //创建包含ip和port的网络节点对象
            IPEndPoint endpoint = new IPEndPoint(address, int.Parse(txtPort.Text));
            //将负责监听的套接字绑定到唯一的ip和端口上
            socketWatch.Bind(endpoint);
            //设置监听队列的长度.
            socketWatch.Listen(10);//最多能同时处理10个,根据服务器配置

            threadWatch = new Thread(WatchConnction);
            threadWatch.IsBackground = true;
            threadWatch.Start();

          
            SHowMsg("服务器启动监听成功!!");
       
            //IPEndPoint

        }

3.服务端接收客户端发来的消息.

 /// <summary>
       /// 服务端负责监听客户端发送来的数据的方法
       /// </summary>
        void RecMSG(Object socketClientpara)
        {
            Socket socketClient = socketClientpara as Socket;
            while (true)
            { 
                 
                byte[] arrMsgRec=new  byte[1024*1024*2];
                int length = -1;
                try
                {
                    length = socketClient.Receive(arrMsgRec);
                }
                catch (SocketException ex)
                {

                    SHowMsg("异常 " + ex.Message);
                    //从通信套接字 集合中删除 被中断连接的通信套接字对象
                    dict.Remove(socketClient.RemoteEndPoint.ToString());
                    //从通信线程 集合中 删除被终端连接的通信线程对象
                    dictThread.Remove(socketClient.RemoteEndPoint.ToString());
                    lboOnline.Items.Remove((socketClient.RemoteEndPoint));

                    break;
                }
                catch (Exception ex)
                {
                    SHowMsg("异常 " + ex.Message);
                    break;
                }
            
                 if (arrMsgRec[0] == 1)//如果是1,则代表发送过来的是文件.
                {
                    SaveFileDialog sfd = new SaveFileDialog();
                  
                    if (sfd.ShowDialog(this) == DialogResult.OK)
                    {
                        string fileSavePath = sfd.FileName;
                        using (FileStream fs = new FileStream(fileSavePath, FileMode.Open))
                        {
                            fs.Write(arrMsgRec, 1, length - 1);
                            SHowMsg("文件保存成功:" + fileSavePath);
                        }
                    }
                
                }
                 else if (arrMsgRec[0] == 0)
                 {
                     string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length-1);
                     SHowMsg(strMsgRec);
                 }
            }
        }

总结:

在服务端,启动监听服务,当监听到有客户端请求的时候,就可以建立TCP/IP连接了。


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值