cari
Rumahpembangunan bahagian belakangTutorial C#.NetC#网络编程的图文代码详解

C#网络编程的图文代码详解

Mar 28, 2017 am 11:20 AM
c#pengaturcaraan rangkaian

在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践,需要的朋友可以参考下

阅读目录:

基础
Socket编程
多线程并发
阻塞式同步IO

基础
在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践。
Socket是一种网络编程接口,它是对传输层TCP、UDP通信协议的一层封装,通过友好的API暴露出去,方便在进程或多台机器间进行网络通信。

Socket编程

在网络编程中分客户端和服务端两种角色,比如通过打开浏览器访问到挂在Web软件上的网页,从程序角度上来看,即客户端(浏览器)发起了一个Socket请求到服务器端,服务器把网页内容返回到浏览器解析后展示。在客户端和服务端数据通信前,会进行三次确认才会正式建立连接,也即是三次握手。

  1. 客户端发送消息询问服务端是否准备好

  2. 服务端回应我准备好了,你呢准备好了吗

  3. 客户端回应服务端我也准备好了,可以通信了

TCP/IP协议是网络间通信的基础协议,在不同编程语言及不同操作系统下暴露的Socket接口用法也大同小异,仅是其内部实现有所不同,比如Linux下的epoll和windows下的IOCP。

服务端
  • 实例化Socket

  • 把公共地址端口绑定操作系统上

  • 开始监听绑定的端口

  • 等待客户端连接

IPEndPoint ip = new IPEndPoint(IPAddress.Any, 6389);
      Socket listenSocket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
      listenSocket.Bind(ip);
      listenSocket.Listen(100);
      listenSocket.Accept();

listen函数中有个int类型参数,它表示最大等待处理连接的数量,表示已建立连接但还未处理的数量,每调用Accept函数一下即从这个等待队列中拿出一个连接。 通常服务端要服务多个客户端请求的连接,所以会循环从等待队列中拿出连接,进行接收发送。

while (true) 
      { 
        var accept= listenSocket.Accept();
        accept.Receive(); 
        accept.Send(); 
      }

多线程并发
上面的服务端程序处理接收和发送消息都是在当前线程下完成的,这意味着要处理完一个客户端连接后才能去处理下一个连接,如果当前连接是进行数据库或者文件读取写入等IO操作,那会极大浪费服务器的CPU资源,降低了服务器吞吐量。

while (true)
      {
        var accept = listenSocket.Accept();
        ThreadPool.QueueUserWorkItem((obj) =>
        {
          byte[] receive = new byte[100];
          accept.Receive(receive);
          byte[] send = new byte[100];
          accept.Send(receive);
        });
      }

如例子中,当监听到有新连接请求过来时,调用Accept()取出当前连接的socket,使用新的线程去处理接收和发送信息,这样服务端就能实现并发处理多个客户端了。 上述代码中,在高并发下其实是有问题的,如果客户端连接请求成千上万个,那线程数量也会有这么多,每个线程的栈空间都需要消耗部分内存,再加上线程上下文切换,容易导致服务器负载过高,吞吐量大大下降,严重时会引起宕机。 当前例子中使用系统ThreadPool的话,线程数量会固定在一个数量上,默认是1000,不会无限制开线程,会把处理超出线程数量的请求放到线程池中的队列上面。
在unix下类似的实现有2种:

fork一个新进程去处理客户端的连接:

var connfd = Accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); 
var m = fork(); 
if(m == 0) 
{
 //do something 
}

创建一个新的线程处理限流:

var *clientsockfd = accept(serversockfd,(struct sockaddr *)&clientaddress, (socklent *)&clientlen);
 if(pthreadcreate(&thread, NULL, recdata, clientsockfd)!=0) 
{ //do something 
}

阻塞式同步IO
上述例子中使用的即是该模型,使用起来简单方便。

while (true)
      {
        var accept = listenSocket.Accept();
        byte[] receive = new byte[100];
        accept.Receive(receive);
        byte[] send = new byte[100];
        accept.Send(receive);
      }

从调用Receive函数起到接受到客户端发过来的数据期间,该函数会一直阻塞等待着,这个阻塞期间处理流程如下:

  1. 客户端发送数据

  2. 通过广域网局域网发送到服务端机器网卡缓冲区上

  3. 网卡驱动对CPU发送中断指令

  4. CPU把数据拷贝到内核缓冲区

  5. CPU再把内核缓冲区的数据拷贝用户缓冲区,上面的receive字节数组。

至此处理成功,开始处理下一个连接请求。 调用发送函数同样会阻塞在当前,然后把用户缓冲区(send字节数组)数据拷贝到内核中TCP发送缓冲区中。 TCP的发送缓冲区也有一定的大小限制,如果发送的数据大于该限制,send函数会一直等待发送缓冲区有空闲时完全拷贝完才会返回,继续处理后续连接请求。

异步IO
上篇提到用多线程处理多个阻塞同步IO而实现并发服务端,这种模式在连接数量比较小的时候非常适合,一旦连接过多,性能会急速下降。 在大多数服务端网络软件中会采用一种异步IO的方式来提高性能。

同步IO方式:连接Receive请求->等待->等待->接收成功
异步IO方式:连接Receive请求->立即返回->事件或回调通知
采用异步IO方式,意味着单线程可以处理多个请求了,连接发起一个Receive请求后,当前线程可以立即去做别的事情,当数据接收完毕通知线程处理即可。
其数据接收分2部分:

数据从别的机器发送内核缓冲区
内核缓冲区拷贝到用户缓冲区
第二部分示例代码:

byte[] msg = new byte[256]; socket.Receive(msg);

介绍这2部分的目的是方便区分其他几种方式。 对于用户程序来说,同步IO和异步IO的区别在于第二部分是否需要等待。

非阻塞式同步IO
非阻塞式同步IO,由同步IO延伸出来,把这个名词拆分成2部分描述:

  • 非阻塞式,指的是上节"数据从别的机器发送内核缓冲区"部分是非阻塞的。

  • 同步IO,指的是上节"内核缓冲区拷贝到用户缓冲区"部分是等待的。

既然是第一部分是非阻塞的,那就需要一种方法得知什么时候内核缓冲区是OK的。 设置非阻塞模式后,在连接调用Receive方法时,会立即返回一个标记,告知用户程序内核缓存区有没有数据,如果有数据开始进行第二部分操作,从内核缓冲区拷贝到用户程序缓冲区。 由于系统会返回个标记,那可以通过轮询方式来判断内核缓冲区是否OK。

设置非阻塞模式参考代码:

SocketInformation sif=new SocketInformation();
sif.Options=SocketInformationOptions.NonBlocking;
sif.ProtocolInformation = new byte[24];
Socket socket = new Socket(sif);

轮询参考代码:

while(true) 
{
byte[] msg = new byte[256];
var temp = socket.Receive(msg);
if (temp=="OK"){
//do something
}else{ continue }
}

这种方式近乎淘汰了,了解即可。

基于回调的异步IO
上面介绍过:

异步IO方式:连接Receive请求->立即返回->事件或回调通知
当回调到执行时,数据已经在用户程序缓冲区已经准备好了,在回调代码中对这部分数据进行相应的逻辑即可。

发出接收请求:

static byte[] msg = new byte[256]; 
var temp = socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(ReadCallback), socket);

回调函数中对数据做处理:

public static void ReadCallback(IAsyncResult ar) 
{ 
var socket = (Socket)ar.AsyncState;
 int read = socket.EndReceive(ar);
DoSomething(msg); 
socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(Read_Callback), socket);
}

当回调函数执行时,表示数据已经准备好,需要先结束接收请求EndReceive,以便第二次发出接收请求。 在服务端程序中要处理多个客户端的接收,再次发出BeginReceive接收数据请求即可。

这里的回调函数是在另外一个线程的触发,必要时要对数据加锁防止数据竞争:

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

Atas ialah kandungan terperinci C#网络编程的图文代码详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
C# .NET Ecosystem: Rangka Kerja, Perpustakaan, dan AlatC# .NET Ecosystem: Rangka Kerja, Perpustakaan, dan AlatApr 24, 2025 am 12:02 AM

Ekosistem C#.NET menyediakan rangka kerja dan perpustakaan yang kaya untuk membantu pemaju membina aplikasi dengan cekap. 1.asp.NetCore digunakan untuk membina aplikasi web berprestasi tinggi, 2.EntityFrameworkCore digunakan untuk operasi pangkalan data. Dengan memahami penggunaan dan amalan terbaik alat -alat ini, pemaju dapat meningkatkan kualiti dan prestasi aplikasi mereka.

Menggunakan C# .NET Aplikasi ke Azure/AWS: Panduan Langkah demi LangkahMenggunakan C# .NET Aplikasi ke Azure/AWS: Panduan Langkah demi LangkahApr 23, 2025 am 12:06 AM

Bagaimana cara menggunakan aplikasi C# .net ke Azure atau AWS? Jawapannya ialah menggunakan Azureappservice dan AwselasticBeansTalk. 1. Pada Azure, mengautomasikan penggunaan menggunakan Azureappservice dan Azurepipelines. 2. Pada AWS, gunakan Amazon ElasticBeansTalk dan AWSLambda untuk melaksanakan penempatan dan pengiraan tanpa pelayan.

C# .NET: Pengenalan kepada bahasa pengaturcaraan yang kuatC# .NET: Pengenalan kepada bahasa pengaturcaraan yang kuatApr 22, 2025 am 12:04 AM

Gabungan C# dan .NET menyediakan pemaju dengan persekitaran pengaturcaraan yang kuat. 1) C# menyokong polimorfisme dan pengaturcaraan asynchronous, 2) .NET menyediakan keupayaan silang platform dan mekanisme pemprosesan serentak, yang menjadikannya digunakan secara meluas dalam pembangunan aplikasi desktop, web dan mudah alih.

Rangka Kerja .NET vs C#: Menyahkodkan istilahRangka Kerja .NET vs C#: Menyahkodkan istilahApr 21, 2025 am 12:05 AM

.NetFramework adalah kerangka perisian, dan C# adalah bahasa pengaturcaraan. 1..NetFramework menyediakan perpustakaan dan perkhidmatan, sokongan desktop, web dan aplikasi mudah alih. 2.C# direka untuk .NetFramework dan menyokong fungsi pengaturcaraan moden. 3..NetFramework Menguruskan pelaksanaan kod melalui CLR, dan kod C# disusun ke IL dan dikendalikan oleh CLR. 4. Gunakan .NetFramework untuk membangunkan aplikasi dengan cepat, dan C# menyediakan fungsi lanjutan seperti LINQ. 5. Kesilapan umum termasuk penukaran jenis dan kebuntuan pengaturcaraan tak segerak. Alat VisualStudio diperlukan untuk debugging.

Demystifying C# .NET: Gambaran Keseluruhan untuk PemulaDemystifying C# .NET: Gambaran Keseluruhan untuk PemulaApr 20, 2025 am 12:11 AM

C# adalah bahasa pengaturcaraan yang berorientasikan objek yang dibangunkan oleh Microsoft, dan .NET adalah rangka kerja pembangunan yang disediakan oleh Microsoft. C# menggabungkan prestasi C dan kesederhanaan Java, dan sesuai untuk membina pelbagai aplikasi. Rangka kerja .NET menyokong pelbagai bahasa, menyediakan mekanisme pengumpulan sampah, dan memudahkan pengurusan memori.

C# dan runtime .net: bagaimana mereka bekerjasamaC# dan runtime .net: bagaimana mereka bekerjasamaApr 19, 2025 am 12:04 AM

C# dan .NET Runtime bekerjasama rapat untuk memperkasakan pemaju untuk keupayaan pembangunan yang cekap, kuat dan silang platform. 1) C# adalah bahasa pengaturcaraan yang berorientasikan objek dan berorientasikan objek yang direka untuk mengintegrasikan dengan lancar dengan rangka .NET. 2) Runtime NET menguruskan pelaksanaan kod C#, menyediakan pengumpulan sampah, keselamatan jenis dan perkhidmatan lain, dan memastikan operasi yang cekap dan silang platform.

C# .NET Development: Panduan Pemula untuk BermulaC# .NET Development: Panduan Pemula untuk BermulaApr 18, 2025 am 12:17 AM

Untuk memulakan C# .NET Development, anda perlu: 1. Memahami pengetahuan asas C# dan konsep teras Rangka Kerja NET; 2. Menguasai konsep asas pembolehubah, jenis data, struktur kawalan, fungsi dan kelas; 3. Belajar ciri -ciri canggih C#, seperti LINQ dan pengaturcaraan asynchronous; 4. Berkenaan dengan teknik debugging dan kaedah pengoptimuman prestasi untuk kesilapan biasa. Dengan langkah -langkah ini, anda secara beransur -ansur boleh menembusi dunia C#.net dan menulis aplikasi yang cekap.

C# dan .net: memahami hubungan antara kedua -duaC# dan .net: memahami hubungan antara kedua -duaApr 17, 2025 am 12:07 AM

Hubungan antara C# dan .NET tidak dapat dipisahkan, tetapi mereka bukan perkara yang sama. C# adalah bahasa pengaturcaraan, sementara .NET adalah platform pembangunan. C# digunakan untuk menulis kod, menyusun bahasa pertengahan .NET (IL), dan dilaksanakan oleh Runtime .NET (CLR).

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

SublimeText3 versi Inggeris

SublimeText3 versi Inggeris

Disyorkan: Versi Win, menyokong gesaan kod!

SublimeText3 Linux versi baharu

SublimeText3 Linux versi baharu

SublimeText3 Linux versi terkini

Versi Mac WebStorm

Versi Mac WebStorm

Alat pembangunan JavaScript yang berguna

mPDF

mPDF

mPDF ialah perpustakaan PHP yang boleh menjana fail PDF daripada HTML yang dikodkan UTF-8. Pengarang asal, Ian Back, menulis mPDF untuk mengeluarkan fail PDF "dengan cepat" dari tapak webnya dan mengendalikan bahasa yang berbeza. Ia lebih perlahan dan menghasilkan fail yang lebih besar apabila menggunakan fon Unicode daripada skrip asal seperti HTML2FPDF, tetapi menyokong gaya CSS dsb. dan mempunyai banyak peningkatan. Menyokong hampir semua bahasa, termasuk RTL (Arab dan Ibrani) dan CJK (Cina, Jepun dan Korea). Menyokong elemen peringkat blok bersarang (seperti P, DIV),