黄巾之乱-网络模块
来源:互联网 发布:网络图片 侵权 编辑:程序博客网 时间:2024/04/27 09:24
服务器端,对应于一个客户端都有一个对象,这些对象被放到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函数,没有为每个连接建立单独的线程,服务器程序才几个线程就可以应付了。
- 黄巾之乱-网络模块
- 黄巾之乱-开发环境
- 黄巾之乱-历次版本
- 黄巾之乱-服务器线程控制
- OpenStack之网络模块
- Webkit之网络模块
- 网络模块之retrofit
- pythonの鉴黄之路(四)——urllib模块批量下载
- Ajax之"黄褪"效果
- 黄
- 感冒之乱思
- 乱战之悬崖勒马
- 移植之乱谈
- 移植之乱谈
- 乱入之青春
- 平定igb之“乱”
- 编译器之乱
- 黄聪:Scrapy 轻松定制网络爬虫
- quartus9.0下载地址
- 图解LoadRunner实现SOAP接口性能测试
- Android Studio创建百度地图
- ASP.NET自定义日志记录
- android-在代码中实现按下Home键的效果
- 黄巾之乱-网络模块
- 最大间隙问题
- C#从数据库中读取数据加入到combox的items中,并显示出当前model值在combox中
- C语言 编写一个函数reverse_string(char * string) 实现:将参数字符串中的字符反向排列。
- IBM X3650 安装ESXi 5.1u2 需要更改BIOS缺省设置
- 使用xadmin替换django自带的admin后台
- 程序员读书雷达
- scheme中if作为特殊形式而不是普通过程的原
- 解决failed to build gem native extension on windows 7