年底了,人浮躁多了,沉不下去心研究技术了,不过昨天终于抢到了回家的票,很开心。
言归正卷,在WCF出来之后,可能我们玩这些原始的TCP越来越少了,我们知道WCF对TCP进行了再一次的包装,第一反应给我们的或许是
同构系统用TCP,异构系统用HTTP,那么问题来了,异构系统到底可不可以用TCP呢?至少WCF是玩不了的,因为其他语言没有针对.net的“服务
引用”,也没有什么ChannelFactory给你去玩,如果你是一定要追求性能的话,原始的TCP会助你一臂之力的。
我们知道最最原始的是玩Socket,由于Socket比较复杂,但是最灵活,C#里面提供了两个简化的包装类:TcpListener和TcpClient。
一:TcpListener
这个是作为服务器端程序而存在的,我们来看看如何使用这服务端。
1: 开启监听地址
1 TcpListener listener = new TcpListener(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);2 3 listener.Start();
2:好了,已经开启了,服务端程序开始监听该端口的客户端请求了,那么如何获取该请求呢?简单,listener的AcceptTcpClient属性搞定。
1 var myclient = listener.AcceptTcpClient();
<1> 收操作:
1 BinaryReader sr = new BinaryReader(client.GetStream());2 3 //客户端数据4 var data = sr.ReadString();
1 //处理完了之后要返回数据给客户端2 BinaryWriter sw = new BinaryWriter(client.GetStream());3 4 sw.Write(string.Format("当前时间:{0},服务端已经处理完毕!", DateTime.Now));
这里要注意的地方就是AcceptTcpClient是阻塞线程的,直到收到客户端请求才算建立了一个TCP连接,在服务端处理的过程中,后续的客户端的请求将
会处理等待直到前一个请求处理完,说了这么多,就是每一个请求我们都建议开一个线程专门为其服务,类似这样。
1 //接受客户端的连接请求 2 var myclient = listener.AcceptTcpClient(); 3 4 //用工作线程执行用户的请求 5 Task.Factory.StartNew((obj) => 6 { 7 var client = obj as TcpClient; 8 9 client.Close();10 11 }, myclient);
二:TcpClient
客户端也很简单,只要我们Connect一下端口,然后通过NetworkStream再Send一些数据就OK了。
1 TcpClient client = new TcpClient();2 3 client.Connect(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);4 5 BinaryWriter bw = new BinaryWriter(client.GetStream());6 7 bw.Write(string.Format("你好,我来请求你! {0},当前线程:{1}", j, Thread.CurrentThread.ManagedThreadId));
最后我们模拟下,客户端开启100个线程,每个线程请求100次,服务器端对每个线程都用工作线程去处理,是不是找到了netTcpBinding的
感觉,最后一个大家都懂的道理就是线程多了不是好事情。
服务端:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.IO; 7 using System.Threading.Tasks; 8 using System.Threading; 9 using System.Net;10 11 namespace ConsoleApplication112 {13 class Program14 {15 static void Main(string[] args)16 {17 TcpListener listener = new TcpListener(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);18 19 listener.Start();20 21 //用专门的线程来接受请求22 Task.Factory.StartNew(() =>23 {24 //不间断的接受客户端请求25 while (true)26 {27 //接受客户端的连接请求28 var myclient = listener.AcceptTcpClient();29 30 //用工作线程执行用户的请求31 Task.Factory.StartNew((obj) =>32 {33 var client = obj as TcpClient;34 35 BinaryReader sr = new BinaryReader(client.GetStream());36 37 //客户端数据38 var data = sr.ReadString();39 40 //客户端ip41 var ip = (IPEndPoint)client.Client.RemoteEndPoint;42 43 Console.WriteLine("当前时间:{0},接受到了来自IP:{1}:{2},的请求,发来的数据为:{3}", DateTime.Now,44 ip.Address, ip.Port, data);45 46 Thread.Sleep(1000 * 5);47 48 //处理完了之后要返回数据给客户端49 BinaryWriter sw = new BinaryWriter(client.GetStream());50 51 sw.Write(string.Format("当前时间:{0},服务端已经处理完毕!", DateTime.Now));52 53 client.Close();54 55 }, myclient);56 }57 });58 59 Console.WriteLine("服务端已经启动...");60 61 Console.Read();62 }63 }64 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.IO; 7 using System.Threading; 8 using System.Threading.Tasks; 9 10 namespace ConsoleApplication211 {12 class Program13 {14 static void Main(string[] args)15 {16 for (int i = 0; i < 100; i++)17 {18 Task.Factory.StartNew(() =>19 {20 for (int j = 0; j < 100; j++)21 {22 TcpClient client = new TcpClient();23 24 client.Connect(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }), 2222);25 26 BinaryWriter bw = new BinaryWriter(client.GetStream());27 28 bw.Write(string.Format("你好,我来请求你! {0},当前线程:{1}", j, Thread.CurrentThread.ManagedThreadId));29 30 BinaryReader sr = new BinaryReader(client.GetStream());31 32 var s = sr.ReadString();33 34 Console.WriteLine("接受到数据:{0}", s);35 }36 });37 }38 39 Console.Read();40 }41 }42 }