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
- C#网络编程 tcpclient (阻塞异步)
- 一、C#网络编程(TcpListener,TcpClient)
- 二、C#网络编程2(TcpListener,TcpClient)
- C#网络编程-TcpClient、TcpListener、UdpClient
- [C#基础]网络编程(二):TcpListener & TcpClient
- C# TcpClient网络编程传输文件
- 网络编程-阻塞非阻塞同步异步
- WIN网络编程-TCPClient
- SOCKET Communication writen in C# (3) TcpListener 和TcpClient 异步非阻塞
- C#异步网络编程
- c# 异步网络编程
- C#网络编程 异步
- c# 网络异步编程
- C# .net TCPClient 网络监听
- C#.网络编程.TcpListener&TcpClient
- 网络编程之同步,阻塞,异步,非阻塞
- 网络编程之同步,阻塞,异步,非阻塞
- 网络编程之同步,阻塞,异步,非阻塞
- 黑马程序员————多线程概述、同步死锁、线程控制、并发访问
- 测试Handler
- 如何解决秒杀商品时,商品超卖的情况
- There is a relation between gradle-plugin and the gradle version. For example
- 初识angular.js之爱恨情仇
- C#网络编程 tcpclient (阻塞异步)
- hdu 2504 又见gcd
- 二次封装dojo slider
- javascript表单验证
- TS码流封装(一)
- c# 连接SQLite及SQLite使用小结
- java 学习 —— AWT布局组件
- 分享一个连接
- c++ 头文件<cwchar>中常见函数的实现!!!