12篇學通C#網絡編程——第四篇 TCP應用編程


    年底了,人浮躁多了,沉不下去心研究技術了,不過昨天終於搶到了回家的票,很開心。

    言歸正卷,在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();


 3:我們知道TCP傳的是字節流,通過myclient.GetStream()就可以獲取一個NetworkStream,利用這個Stream就可以進行收發信息了。

 <1> 收操作:

1 BinaryReader sr = new BinaryReader(client.GetStream());
2 
3  //客戶端數據
4  var data = sr.ReadString();


<2>發操作:也就是所謂的返回值

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);


好了,服務器端大概就是這個樣子,再有的就是一些相關屬性配置了,像wcf那樣什么opentime,sendtime啥的。

 

二: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的

感覺,最后一個大家都懂的道理就是線程多了不是好事情。

服務端:

View Code
 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 ConsoleApplication1
12 {
13     class Program
14     {
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                         //客戶端ip
41                         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 }


客戶端:

View Code
 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 ConsoleApplication2
11 {
12     class Program
13     {
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 }


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM