黄巾之乱-网络模块

原创 2015年03月26日 11:58:56


 服务器端,对应于一个客户端都有一个对象,这些对象被放到list中,控制了这个list,就控制了整个服务器的通讯。

服务器端的这个对象叫tcpuser, 里面放一些变量,有一个变量比较特别,tcpclient,这个变量以后就是它同客户端建立起通道然后通讯。

public class tcpuser
    {
        public int id { get; set; }
        public TcpClient tcp { get; set; }
        public string username { get; set; }
        public string password { get; set; }
        public string txtin { get; set; }
        public string txtout { get; set; }
        public string heart { get; set; }

    }

tcpuser对象放到一个list对象集中。

public List<tcpuser> tcpuserlist = new List<tcpuser>();

服务器网络模块运行时,需要用一个IP和端口做监听,就是netstat -an中看到的listening, 客户段就用这个端口接入。


既然使用C#,为了最简单,就不去使用socket,直接用tcplistener,很方便。

下面的函数,我放到了一个线程中,这个线程执行起来,它会监听等待用户连接。

 private void server_listen()
        {
            listener = new TcpListener(IPAddress.Any, 3000);
            listener.Start();

            while (true)
            {
                Thread.Sleep(1000);
                while (listener.Pending())  //跳开阻塞,用这个在关闭服务器程序时不会出现异常
                {

                    tcpuser one = new tcpuser();             
                    one.tcp = listener.AcceptTcpClient();
                    NetworkStream stream = one.tcp.GetStream();

                     try {
                            if (stream.CanRead) {  stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallBack), one);  }
                         }
                     catch
                         {
                        
                         }  
                    one.id = tcpuserid;
                    tcpuserlist.Add(one);
                    tcpuserid++;

                }               
            }
        }

上面的代码,当一个客户端接入,服务器会新建一个tcpuser对象,把通过客户端通讯的通道连接到tcpuser对象的一个变量TcpClient 上。

通道建立好后,在这个stream中,使用beginread异步来读取客户端传来的数据。同当前线程中对立的是,这个beginread启动了系统回调功能,系统去处理beginread中的代码,再无需我们关心。只是在beginread代码的最后,不能让它就这么结束了。应该要让它一直接跑作,才能一直接收用户的数据,所有最后,我们让beginread再调用自己,这样就可以一直运行下去。

下面代码就是这个一直自己调用自己的回调函数:

public void ReadCallBack(IAsyncResult ar)
        {         
            try
            {
                tcpuser one = (tcpuser)ar.AsyncState;
                //心跳改变
                one.heart = DateTime.Now.ToString();  
                NetworkStream stream = (NetworkStream)one.tcp.GetStream(); 

                int numberOfBytesRead = stream.EndRead(ar);
                one.txtin = Encoding.UTF8.GetString(buffer, 0, numberOfBytesRead);

                //处理客户端数据
                string[] s = one.txtin.Split('|');
                //如果是1,1 就是认证用的用户密码数据
                if ((int.Parse(s[0]) == 1) && (int.Parse(s[1]) == 1)) { one.username = s[2]; one.password = s[3]; }             
                                
                stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallBack), one);

                //卡了一个写回客户端 
                if (one.txtout != null)
                {
                    wbuffer = Encoding.UTF8.GetBytes(one.txtout);
                    if (stream.CanWrite) { stream.BeginWrite(wbuffer, 0, wbuffer.Length, new AsyncCallback(WriteCall), one); }
                }
            }  
            catch 
            {                  
            }              
        }

这个回调函数,一旦跑起来,就可以一直由系统来处理传入的用户数据,这是一个很好的功能。

客户端一次传入的数据,函数中就近就放在txtin变量中,等服务器其它模块来处理,反正网络模块就只能处理到这里了。

其它模块只需要遍历tcpuser 这个list,取出来看看txtin变量,就知道客户端想做什么。

目前我干脆把写回客户端的功能,也放到了里面。 还加入了心跳功能,解析一种客户端数据的功能。

心跳功能,其实就是在回调函数中不停的刷新heart这个变量,

回调函数是基于通道stream的,如果客户端退出,通道就关闭,stream就会无效,回调函数就会停工。

心跳变量就会停止刷新,检查心跳变量,没有刷新的,就是客户端已经退出的对应于服务器的tcpuser对象。



基于上面的设计,先搞了一个原型出来,测试了一下。

模拟了500个客户端连接服务器,每秒发送一串字符。

服务器使用beginread函数,没有为每个连接建立单独的线程,服务器程序才几个线程就可以应付了。


版权声明:本文为博主原创文章,未经博主允许不得转载。

新游戏发布《三国记黄巾之乱》—新引擎预热

一,关于引擎: 《三国记黄巾之乱》是用鄙人新开发的flash脚本引擎LegendForFlashProgramming0.1制作而成,该引擎完全脱离光荣原版引擎,关于新引擎的下载和使用方法, 请看...

关于PL2303型号命名之乱

转自:http://www.360doc.com/content/13/0916/16/6973384_314860320.shtml 使用PL2303这款芯片制作USB转串口时,相信很多人对PL2...

移植之乱谈

昨天有一个博友回复,说他已经完成了android系统在windows上的移植,其中比较难的是binder系统的移植。下面是两个demo网址,我看了后倍有感触。http://v.youku.com/v_...
  • Innost
  • Innost
  • 2011年11月10日 07:34
  • 6669

风控之乱:零经验者,跳槽3次,年薪50万 2016-10-20 20:06 来源:一本财经(yibencaijing) 本文经授权转载!感谢原作者的辛勤创作! 金融的核心是什么? 严谨的金融从业者,

风控之乱:零经验者,跳槽3次,年薪50万 2016-10-20 20:06 来源:一本财经(yibencaijing) 本文经授权转载!感谢原作者的辛勤创作! 金融...

Android渠道不能承受之乱

你经常在哪里下Android软件?答案可能五花八门。第九城市副总裁沈国定不久前刚刚拿到一部HTC水货手机,里面居然被刷进超过10个软件商店,谷歌官方的Android Market、安智市场、安卓市...

编译器之乱

编译器之乱在学习C语言的一年中,我用了许多工具:DEV C++,GCC,VS2017。大概两月前,我发现一件有趣的事:一模一样的代码,在VS中无法运行,却能在DEV上运行。对于这件事,我一直没怎么上心...

【转】移植之乱谈 深入理解Android 卷I作者谈

昨天有一个博友回复,说他已经完成了android系统在windows上的移植,其中比较难的是binder系统的移植。下面是两个demo网址,我看了后倍有感触。 http://v.youk...
  • ilvu999
  • ilvu999
  • 2012年09月03日 23:57
  • 483

SQL之乱笔--从基础开始

-----------------------日期星期的计算--------------------------------------- declare @Date datetime=getdat...

JavaServlet之乱码(一)

web.xml除了可以配置Servlet的浏览器访问路径之处,还可以为我们的网站配置首页。 配置首页的方式如下: 1.html MyEclipse里的src目录(src目录是放java源代码文...

oracle 数据备份服务器安装 之乱码篇

服务器:win2003系统 数据库:oracle10.2.1 forwindows32 参考文献: 解決EXP-00091的方法:http://www.blogjava.net/nobody...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:黄巾之乱-网络模块
举报原因:
原因补充:

(最多只允许输入30个字)