关闭

黄巾之乱-网络模块

387人阅读 评论(0) 收藏 举报
分类:


 服务器端,对应于一个客户端都有一个对象,这些对象被放到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函数,没有为每个连接建立单独的线程,服务器程序才几个线程就可以应付了。


0
0

猜你在找
深度学习基础与TensorFlow实践
【在线峰会】前端开发重点难点技术剖析与创新实践
【在线峰会】一天掌握物联网全栈开发之道
【在线峰会】如何高质高效的进行Android技术开发
机器学习40天精英计划
Python数据挖掘与分析速成班
微信小程序开发实战
JFinal极速开发企业实战
备战2017软考 系统集成项目管理工程师 学习套餐
Python大型网络爬虫项目开发实战(全套)
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:99782次
    • 积分:674
    • 等级:
    • 排名:千里之外
    • 原创:2篇
    • 转载:3篇
    • 译文:0篇
    • 评论:24条
    个人说明

    SAP-BASIS 14年
    SAP-ABAP 3年

    QQ:522929
    个人IT技术里程碑
    1999 Computer hardware、TurboC2.0
    2000 电信局端接入设备
    2001 CISCO Routers
    2002 SAP46C、BASIS
    2003 VC6++ MFC
    2004 JX外挂
    2005 ASP
    2006 黄巾之乱第一版、JSP、AJAX、JS、MSSQL2000
    2007 HP-UX ORACLE Reorganization
    2008 JXSJ外挂,hook API
    2009 黄巾之乱第二版、AS3、hibernate、MSSQL2005
    2010 AIX DB2 ECC6 BASIS
    2011 www.haoshangpin.net 淘宝客WEB
    2012 选号程序
    2013 VMware平台、京东销售联盟
    2014 ECC6EHP7 BASIS
    2015 C#、ABAP
    2016 WMS项目、EF6、FineUI、SAP BI42
    2017 UNITY2D
    最新评论