zoukankan      html  css  js  c++  java
  • 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 }


  • 相关阅读:
    python 判断矩阵中每行非零个数的方法
    用Python 绘制分布(折线)图
    统计numpy数组中每个值出现的个数
    pandas 获取不符合条件的dataframe
    Python 中如何判断 list 中是否包含某个元素
    docker与Spring boot的集成:docker-maven-plugin使用
    处理kdevtmpfsi挖矿病毒
    使用docker-maven-plugin推送镜像到远程docker服务器
    docker 开启2375端口,提供外部访问docker
    Spring Boot 配置优先级顺序
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/2866492.html
Copyright © 2011-2022 走看看