C#网络编程 tcpclient (阻塞异步)

来源:互联网 发布:大数据金融论坛 编辑:程序博客网 时间:2024/04/30 03:02

C# 高效的语言,既然选择了它来写网络服务器,就应该使用最简单的方式。

MS提供了SOCKET和TCPCLIENT两种方式给我们使用,TCPCLIENT封装了socket,似乎应该用tcpclient来搞。。。



关于阻塞:

该概念出现的场景是服务器端,在接受客户端连接的场景。我们在服务器端用TcpListener打开一个监听,等待客户端的连接,需要使用AcceptTcpClient()方法。

这个AcceptTcpClient()方法一旦使用,整个线程就停住(阻塞)了。  直到有客户端连接上来后,AcceptTcpClient()方法才返回客户端的连接。


关于异步:

该概念出现在网络连接已经建立好后的场景,服务器程序或客户端程序,从连接的数据流里面读取或写入数据,如果数据流中有数据才读取,程序代码跟着执行就是同步,

或者不管有无数据,都去试做读数据流中的数据,而使用回调函数来处理这摊子事情,就是异步。



基于TCPCLIENT,下面使用简单的代码来实现一个阻塞,异步的网络服务器。


服务器开始,使用一个线程来处理监听操作:


            Thread lsThread = new Thread(new ThreadStart(server_listen));            lsThread.IsBackground = true;            lsThread.Start();



        //////////////////        /////网络监听////        /////////////////        private void server_listen()        {            listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 3000);            listener.Start();            while (true)            {                Thread.Sleep(1000);                while (listener.Pending())  //跳开阻塞,用这个在关闭服务器程序时不会出现异常                {                    tcpuser one = new tcpuser();                    one.tcp = listener.AcceptTcpClient();                                                            Thread subThread = new Thread(new ParameterizedThreadStart(f1)); //线程                    subThread.Start(one);                                                                              gv.tcpuserlist.Add(one);                  }            }        }

关于listener.Pending,这个方法可以测试listener中有没有客户端连接上来,如果有,再去接收客户端的连接。

这样的写法,就可以避免程序被直接使用AcceptTcpClient()方法阻塞住。



        //多客户端的处理线程        private void f1(object xxx)        {            tcpuser tp = (tcpuser)xxx;            NetworkStream stream = tp.tcp.GetStream();                        while (true)            {                var begint = DateTime.Now;                rwl.EnterReadLock(); //无论花费多长时间,线程都会一直等到获得锁为止                                try                {                        //对话逻辑处理                         client_business(tp);                                                //网络写                                                if (!String.IsNullOrWhiteSpace(tp.txtout))                        {                            tp.writebuffer = Encoding.UTF8.GetBytes(tp.txtout + "."); //加一次消息结束符号.                            if (tp.tcp != null && tp.tcp.Connected)                            {                                if (stream.CanWrite) { stream.BeginWrite(tp.writebuffer, 0, tp.writebuffer.Length, new AsyncCallback(WriteCallBack), tp); }                            }                            else { tp.islogon = 0; rwl.ExitReadLock(); break; }                        }                                                //网络读                        if (tp.tcp != null && tp.tcp.Connected) { stream.BeginRead(tp.readbuffer, 0, tp.readbuffer.Length, new AsyncCallback(ReadCallBack), tp); }                        else { tp.islogon = 0; rwl.ExitReadLock(); break; }                                     }                catch { listBox2.Items.Insert(0, "对话模块 ERROR"); tp.islogon = 0; rwl.ExitReadLock(); break; }                Thread.Sleep(100);                                rwl.ExitReadLock();                listBox1.Items.Insert(0, tp.playername + " client:" + Convert.ToInt32(DateTime.Now.Subtract(begint).TotalMilliseconds).ToString());                                         }        }


上面的代码使用BeginRead来读取流中的数据,BeginRead方法是一个回调函数,WIN系统会处理函数中的代码,并且它自己结束时候,又调用了自己,就形成了一个循环,可以不停的处理数据。


下面是BeginRead函数的代码内容:


        //网络读子函数        public void ReadCallBack(IAsyncResult ar)        {            try            {                tcpuser one = (tcpuser)ar.AsyncState;                if (one.tcp != null && one.tcp.Connected)                {                    NetworkStream stream = (NetworkStream)one.tcp.GetStream();                    int numberOfBytesRead = stream.EndRead(ar);                    one.txtin = Encoding.UTF8.GetString(one.readbuffer, 0, numberOfBytesRead);                                     if (!String.IsNullOrWhiteSpace(one.txtin))                    { one.txtlonglong = one.txtlonglong + one.txtin;  one.txtin = ""; } //每次收到的,都放longlong                }            }            catch { listBox2.Items.Insert(0, "ReadCallBack ERROR"); }        }        //网络写子函数        public void WriteCallBack(IAsyncResult ar)        {            try            {                tcpuser one = (tcpuser)ar.AsyncState;                if (one.tcp != null && one.tcp.Connected)                {                    NetworkStream stream = (NetworkStream)one.tcp.GetStream();                    stream.EndWrite(ar);                    one.txtout = "";                }            }            catch { listBox2.Items.Insert(0, "WriteCallBack ERROR");  }        }


















0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果平板充电时显示不在充电怎么办 苏州驾校考试科目二挂了两次怎么办 支付宝收款码少收钱了怎么办 支付宝发的红包不领取怎么办 微信存在风险不能领红包怎么办 天猫超市电话写错了怎么办 天猫买东西地址写错了怎么办 天猫上买衣服收货电话写错了怎么办 电视遥控器不小心按了高清键怎么办 康佳电视打开右下角是红色的怎么办 天猫超市退款成功后收到货怎么办 天猫还没收到货就确认收货了怎么办 支付宝红包抵扣被关了怎么办 水貂绒大衣白色过色了怎么办 双面羊绒大衣袖子洗短了怎么办 特殊类型订单销量评价删除后怎么办 淘宝上卖家发货发错了地址怎么办 买完保险想换保险代理人怎么办 怀孕内裤两边磨的好疼怎么办 露肩连体裤穿着卡裆怎么办 魅族手机恋与制作人换诺基亚怎么办 蚊子叮咬后擦风油精了红肿怎么办 机动车已转让没过户出了事情怎么办 签好的合同如果甲方违约怎么办? 饭店没签合同辞职不给工资怎么办 两家为了带孩子闹翻了怎么办啊? 抵押后租赁的房屋被法院拍卖怎么办 房子买20年了没有过户怎么办 二手车没过户行驶证丢了怎么办 买的二手车行驶证丢了怎么办 在京东仓库做事把东西损坏了怎么办 微信显示该账号登陆环境异常怎么办 干洗店把衣服洗坏了怎么办 千牛上怎么改淘宝密码忘记了怎么办 公司收了代理商押金到期不退怎么办 淘宝显示签收但是我没收到货怎么办 淘宝东西没收到显示签收了怎么办 开拼多多店铺的密码忘了怎么办 拼多多密码跟店铺名忘了怎么办 闲鱼上卖出的宝贝被调包了怎么办 上传身份证照片说格式错误该怎么办