Heim Backend-Entwicklung C#.Net-Tutorial Detaillierte Erläuterung des grafischen Codes der C#-Netzwerkprogrammierung

Detaillierte Erläuterung des grafischen Codes der C#-Netzwerkprogrammierung

Mar 28, 2017 am 11:20 AM
c# 网络编程

In der heutigen Softwareentwicklung ist die Netzwerkprogrammierung ein sehr wichtiger Teil. In diesem Artikel werden die Konzepte und Praktiken der Netzwerkprogrammierung kurz vorgestellt. Freunde, die sie benötigen, können sich auf das

-Leseverzeichnis beziehen :

Grundlagen

Socket-Programmierung
Multithread-Parallelität
Blockierung synchroner E/A

GrundlagenIn der heutigen Softwareentwicklung ist Netzwerkprogrammierung wichtig sehr wichtig In diesem Artikel werden als wichtiger Teil kurz die Konzepte und Praktiken der Netzwerkprogrammierung vorgestellt.
Socket ist eine Netzwerkprogrammierschnittstelle. Es handelt sich um eine Kapselungsschicht der Transportschicht-TCP- und UDP-Kommunikationsprotokolle. Es wird über eine benutzerfreundliche API bereitgestellt, um die Netzwerkkommunikation zwischen Prozessen oder mehreren Maschinen zu erleichtern.

Socket-Programmierung
Bei der Netzwerkprogrammierung gibt es zwei Rollen: Client und Server. Durch Öffnen eines Browsers können Sie beispielsweise auf das Programm zugreifen hängt an der Web-Software. Aus Programmsicht bedeutet eine Webseite, dass der Client (Browser) eine Socket-Anfrage an den Server initiiert und der Server den Inhalt der Webseite zur Analyse und Anzeige an den Browser zurückgibt. Vor der Datenkommunikation zwischen dem Client und dem Server werden drei Bestätigungen vorgenommen, bevor die Verbindung offiziell hergestellt wird. Dies ist ein Drei-Wege-Handshake.

  1. Client

    Nachricht sendenFragen Sie den Server, ob er bereit ist

  2. Der Server antwortet: Ich bin bereit, was ist mit Ihnen? ? Sind Sie bereit?

  3. Der Client antwortet dem Server, dass ich bereit bin und kommunizieren kann

TCP/IPProtokoll ist das Basisprotokoll für die Kommunikation zwischen Netzwerken. Die Verwendung der Socket-Schnittstelle, die unter verschiedenen Programmiersprachen und verschiedenen Betriebssystemen verfügbar gemacht wird, ist ebenfalls ähnlich, aber ihre interne Implementierung ist unterschiedlich, wie z. B. Linux epoll unter Windows und IOCP unter Windows.

Server
  • Socket instanziieren

  • Den öffentlichen Adressport an das Betriebssystem binden

  • Beginnen Sie mit dem Abhören des gebundenen Ports

  • Warten auf Client-Verbindung

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();
Nach dem Login kopieren
Abhören

Funktion<🎜 Es gibt Ein Parameter vom Typ int in >, der die maximale Anzahl der Verbindungen darstellt, die auf die Verarbeitung warten, und die Anzahl der Verbindungen, die hergestellt, aber noch nicht verarbeitet wurden. Bei jedem Aufruf der Accept-Funktion wird eine Verbindung herausgenommen diese Warteschlange . Normalerweise muss der Server die von mehreren Clients angeforderten Verbindungen bedienen, daher führt er eine Schleife durch, um die Verbindungen aus der Warteschlange zum Empfangen und Senden herauszunehmen.

while (true) 
      { 
        var accept= listenSocket.Accept();
        accept.Receive(); 
        accept.Send(); 
      }
Nach dem Login kopieren

Multi-Thread-Parallelität

Das obige Serverprogramm übernimmt das Empfangen und Senden von Nachrichten im aktuellen Thread Die Clientverbindung muss verarbeitet werden, bevor die nächste Verbindung verarbeitet werden kann. Wenn die aktuelle Verbindung für E/A-Vorgänge wie das Lesen und Schreiben von Datenbanken oder Dateien bestimmt ist, werden die CPU-Ressourcen des Servers stark verschwendet und der Serverdurchsatz verringert.
Wenn wie im Beispiel eine neue Verbindungsanforderung erkannt wird, wird Accept() aufgerufen, um den Socket der aktuellen Verbindung zu entfernen, und ein neuer Thread wird zum Verarbeiten von Empfangs- und Sendeinformationen verwendet. damit der Server

Gleichzeitige Verarbeitung
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);
        });
      }
Nach dem Login kopieren
Mehrere Clients implementieren kann. Im obigen Code gibt es tatsächlich ein Problem bei hoher Parallelität. Wenn Tausende von Threads vorhanden sind, verbraucht jeder Thread einen Teil des Speichers kann leicht zu einer übermäßigen Serverlast, einem stark verringerten Durchsatz und in schweren Fällen zu Ausfallzeiten führen. Wenn im aktuellen Beispiel der System-ThreadPool verwendet wird, wird die Anzahl der Threads auf eine bestimmte Zahl festgelegt, der Standardwert ist 1000 und Threads werden nicht auf unbestimmte Zeit geöffnet. Anforderungen, die die Anzahl der Threads überschreiten, werden in die Warteschlange gestellt Thread-Pool.

Es gibt zwei ähnliche Implementierungen unter Unix: Forken Sie einen neuen Prozess, um Client-Verbindungen zu verwalten:

Erstellen Sie einen neuen Thread, um die Strombegrenzung zu verwalten:

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

Blockieren synchroner E/A
var *clientsockfd = accept(serversockfd,(struct sockaddr *)&clientaddress, (socklent *)&clientlen);
 if(pthreadcreate(&thread, NULL, recdata, clientsockfd)!=0) 
{ //do something 
}
Nach dem Login kopieren

Das Modell wird im obigen Beispiel verwendet und ist einfach und bequem zu verwenden.
Vom Aufruf der Empfangsfunktion bis zum Empfang der vom Client gesendeten Daten blockiert und wartet die Funktion während dieser Blockierungsperiode wie folgt:

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

Der Client sendet Daten
  1. Sendet sie über das WAN-LAN an den Netzwerkkartenpuffer des Servercomputers
  2. Der Netzwerkkartentreiber sendet einen Interrupt-Befehl an die CPU
  3. Die CPU kopiert die Daten in den Kernel-Puffer
  4. Die CPU kopiert dann die Daten Vom Kernel-Puffer zum Benutzerpuffer wird das obige Byte-Array empfangen.

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

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

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

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

byte[] msg = new byte[256]; socket.Receive(msg);
Nach dem Login kopieren

介绍这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);
Nach dem Login kopieren

轮询参考代码:

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

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

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

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

发出接收请求:

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

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

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);
}
Nach dem Login kopieren

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

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

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des grafischen Codes der C#-Netzwerkprogrammierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Crossplay haben?
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Active Directory mit C# Active Directory mit C# Sep 03, 2024 pm 03:33 PM

Leitfaden zu Active Directory mit C#. Hier besprechen wir die Einführung und die Funktionsweise von Active Directory in C# sowie die Syntax und das Beispiel.

C#-Serialisierung C#-Serialisierung Sep 03, 2024 pm 03:30 PM

Leitfaden zur C#-Serialisierung. Hier besprechen wir die Einführung, die Schritte des C#-Serialisierungsobjekts, die Funktionsweise bzw. das Beispiel.

Zufallszahlengenerator in C# Zufallszahlengenerator in C# Sep 03, 2024 pm 03:34 PM

Leitfaden zum Zufallszahlengenerator in C#. Hier besprechen wir die Funktionsweise des Zufallszahlengenerators, das Konzept von Pseudozufallszahlen und sicheren Zahlen.

C#-Datenrasteransicht C#-Datenrasteransicht Sep 03, 2024 pm 03:32 PM

Leitfaden zur C#-Datenrasteransicht. Hier diskutieren wir die Beispiele, wie eine Datenrasteransicht aus der SQL-Datenbank oder einer Excel-Datei geladen und exportiert werden kann.

Muster in C# Muster in C# Sep 03, 2024 pm 03:33 PM

Leitfaden zu Mustern in C#. Hier besprechen wir die Einführung und die drei wichtigsten Arten von Mustern in C# zusammen mit ihren Beispielen und der Code-Implementierung.

Primzahlen in C# Primzahlen in C# Sep 03, 2024 pm 03:35 PM

Leitfaden zu Primzahlen in C#. Hier besprechen wir die Einführung und Beispiele von Primzahlen in C# sowie die Codeimplementierung.

Fakultät in C# Fakultät in C# Sep 03, 2024 pm 03:34 PM

Leitfaden zur Fakultät in C#. Hier diskutieren wir die Einführung in die Fakultät in C# zusammen mit verschiedenen Beispielen und Code-Implementierungen.

Der Unterschied zwischen Multithreading und asynchronem C# Der Unterschied zwischen Multithreading und asynchronem C# Apr 03, 2025 pm 02:57 PM

Der Unterschied zwischen Multithreading und Asynchron besteht darin, dass Multithreading gleichzeitig mehrere Threads ausführt, während asynchron Operationen ausführt, ohne den aktuellen Thread zu blockieren. Multithreading wird für rechenintensive Aufgaben verwendet, während asynchron für die Benutzerinteraktion verwendet wird. Der Vorteil des Multi-Threading besteht darin, die Rechenleistung zu verbessern, während der Vorteil von Asynchron nicht darin besteht, UI-Threads zu blockieren. Die Auswahl von Multithreading oder Asynchron ist von der Art der Aufgabe abhängt: Berechnungsintensive Aufgaben verwenden Multithreading, Aufgaben, die mit externen Ressourcen interagieren und die UI-Reaktionsfähigkeit asynchron verwenden müssen.

See all articles