12.Python3でのネットワークプログラミング

インターネットの本質####

2台のコンピューター間の通信は、2人が電話をかけるという原則と同じです。

# 1. まず、さまざまな物理接続メディアを介して接続する必要があります
# 2. 正確なコンピューターを探す(ソフトウェアに正確)の位置
# 3. 統一された標準を採用する(一般的なサブアグリーメント)データ転送

# 物理的な接続媒体、これはネットワークエンジニアが検討するものであり、後で簡単に説明します。主にこの統一された標準について学習します。

# 英語は世界中のすべての人々の統一されたコミュニケーションの標準になりました。コンピュータが世界中に分散している人々と見なされる場合、2台のコンピュータを接続するインターネットは実際には一連の統一された標準です。これらの標準はインターネットプロトコルと呼ばれます。本質は、「インターネットプロトコルスイート」(インターネットプロトコルスイート)と総称される一連のプロトコルです。).

# インターネットプロトコルの機能:コンピュータがインターネットにアクセスする方法、およびインターネットに接続されたコンピュータ通信の標準を定義します。

インターネットの誕生以来、ほとんどすべてのプログラムがネットワークプログラムになり、スタンドアロンプログラムはほとんどありません。
コンピュータネットワークは、ネットワーク内のコンピュータが相互に通信できるように、コンピュータを相互に接続します。ネットワークプログラミングは、プログラム内の2台のコンピューター間の通信を実現する方法です。
たとえば、ブラウザを使用してSina.comにアクセスすると、コンピュータはインターネット経由で特定のSinaサーバーに接続され、SinaのサーバーはWebコンテンツをデータとしてインターネット経由でコンピュータに転送します。
お使いのコンピュータはブラウザだけでなく、QQ、Skype、Dropbox、メールクライアントなどでもあるため、異なるプログラムに接続されている他のコンピュータも異なります。より正確には、ネットワーク通信は2台のコンピュータ上で行われます。 2つのプロセス間の通信。たとえば、ブラウザプロセスはSinaサーバー上の特定のWebサービスプロセスと通信し、QQプロセスはTencentサーバー上の特定のプロセスと通信します。

TCP / IP ####の概要

誰もがインターネットに精通していますが、コンピュータネットワークはインターネットよりはるかに早く登場しました。
コンピューターをインターネットに接続するには、通信プロトコルを指定する必要があります。初期のコンピューターネットワークでは、各メーカーが一連のプロトコルを指定していました。IBM、Apple、Microsoftには、相互に互換性のない独自のネットワークプロトコルがあります。英語を話す人、中国語を話す人、ドイツ語を話す人がいます。同じ言語を話す人はコミュニケーションできますが、異なる言語間ではコミュニケーションできません。
世界中のさまざまな種類のコンピューターすべてを接続するには、ユニバーサルプロトコルのセットを指定する必要があります。インターネットの目的を達成するために、インターネットプロトコルスイート(インターネットプロトコルスイート)はユニバーサルプロトコル標準です。インターネットは、インターとネットという言葉の組み合わせです。本来の目的は、「ネットワーク」ネットワークに接続することです。インターネットを使用すると、このプロトコルをサポートしている限り、どのプライベートネットワークでもインターネットに接続できます。
インターネットプロトコルには何百ものプロトコル標準が含まれていますが、最も重要な2つのプロトコルはTCPプロトコルとIPプロトコルであるため、誰もがインターネットプロトコルをTCP / IPプロトコルと呼んでいます。
通信するときは、メールを送信するときに相手のメールアドレスを知っている必要があるのと同じように、両方の相手が相手のIDを知っている必要があります。インターネット上の各コンピューターの一意の識別子は、「123.123.123.123」と同様のIPアドレスです。コンピュータがルータなどの2つ以上のネットワークに同時に接続されている場合、そのコンピュータには2つ以上のIPアドレスがあります。したがって、IPアドレスは、コンピュータのネットワークインターフェイス(通常はネットワークカード)に対応します。

IPプロトコルは、ネットワークを介して1つのコンピューターから別のコンピューターにデータを送信する役割を果たします。データは小さな断片に分割され、IPパケットを介して送信されます。インターネットリンクが複雑なため、2台のコンピューター間に複数の回線が存在することが多いため、IPパケットの転送方法を決定するのはルーターの責任です。 IPパケットの特徴は、ブロックで送信され、複数のルートを経由してルーティングされることですが、到着する保証はなく、順番に到着する保証もありません。

IPアドレスは実際には32ビットの整数(IPv4と呼ばれます)です。 192.168.0.1などの文字列で表されるIPアドレスは、実際には読みやすくするために8ビットでグループ化された32ビットの整数です。
IPv6アドレスは実際には128ビットの整数であり、現在使用されているIPv4のアップグレードバージョンであり、「2001:0db8:85a3:0042:1000:8a2e:0370:7334」のような文字列として表されます。
TCPプロトコルはIPプロトコルに基づいています。 TCPプロトコルは、2台のコンピューター間に信頼性の高い接続を確立して、データパケットが順番に到着するようにします。 TCPプロトコルは、ハンドシェイクを介して接続を確立し、各IPパケットに番号を付けて、相手が順番に受信できるようにします。パケットが失われた場合、自動的に再送信されます。
一般的に使用される高レベルのプロトコルの多くは、ブラウザ用のHTTPプロトコル、メール送信用のSMTPプロトコルなど、TCPプロトコルに基づいています。
送信するデータに加えて、TCPメッセージには送信元IPアドレスと宛先IPアドレス、送信元ポートと宛先ポートも含まれます。
ポートは何をしますか? 2台のコンピューターが通信する場合、同じコンピューター上で複数のネットワークプログラムが実行されているため、IPアドレスを送信するだけでは不十分です。 TCPメッセージが到着した後、それがブラウザに配信されるかQQに配信されるかは、それを区別するためのポート番号に依存します。各ネットワークプログラムは、一意のポート番号のオペレーティングシステムに適用されます。このように、2つのプロセスは、2つのコンピューター間のネットワーク接続を確立するために、独自のIPアドレスと独自のポート番号を必要とします。
プロセスは複数のコンピューターとのリンクを確立する場合もあるため、多くのポートに適用されます。

TCP / IPプロトコルの基本概念、IPアドレスとポートの概念を理解したら、ネットワークプログラミングを開始できます。

ソフトウェア開発アーキテクチャ####

CSアーキテクチャ、BSアーキテクチャ#####

クライアントの英語名:クライアント、

ブラウザの英語名:Browser。

サーバーの英語名:Server。

C / Sアーキテクチャ:クライアントとクライアント間のアーキテクチャに基づいています。例:QQ、WeChat、Youku、Baofengyingyinなど。

B / Sアーキテクチャ:C / Sアーキテクチャに基づく特別なC / Sアーキテクチャ、ブラウザとサーバー間のアーキテクチャ。

概要:CSは、応答速度が速く、セキュリティが強力です。一般にローカルエリアネットワークで使用されますが、開発と保守のコストが高くなります。BSは、クロスプラットフォームのクライアント側のゼロ保守を実現できますが、パーソナライズ能力が低く、応答速度が遅くなります。そのため、日常の事務でBSを使用し、実際の生産でCS構造を使用するユニットもあります。

# C/Sアーキテクチャ
	C:クライアント
	S:サーバ

# B/Sアーキテクチャ
	B:ブラウザ
	S:サーバ
        
# C/Sアーキテクチャ:使用するにはインストールする必要があります
# クライアントクライアント:インストールする必要があります
# サーバーサーバー

# B/Sアーキテクチャ:Baidu Blog Park Google Code Cloud
# ブラウザブラウザ
# サーバーサーバー

# b/sとc/s関係は何ですか?
# B/SアーキテクチャはCです/Sアーキテクチャの一種

# C/Sアーキテクチャの利点
# オフラインで使用できます/より完全な機能/より良いセキュリティ

# B/Sアーキテクチャ
# インストールせずに使用できます
# ユニファイドPCユーザーポータル

# モバイル端末:Cのように/Sアーキテクチャは比較的ホットですが、そうではありません。WeChatアプリレットとAlipayサードパーティインターフェイスはBに似ています。/Sアーキテクチャ
# 目的は、インターフェイスを統合することです:ユーザーグループを収集する

# PC側:BSの方が人気です
# 自然: B/Sアーキテクチャ自体もCです/Sアーキテクチャ

クライアントとサーバーの概念

# サーバ:24時間サービスを提供します、私は来る人にサービスを提供します
# クライアント:サービスを体験したいときは、サーバーに行ってサービスを体験してください

` ネットワークプログラミングを学ぶために何ができますか?

# 開発C/Sアーキテクチャソフトウェア

並行性、データベース、フロントエンドで何ができるかを学ぶ

# 開発B/Sアーキテクチャソフトウェア

ネットワークプログラミング技術の起源

# 最も先進的な技術の台頭は基本的に軍隊から来ており、ネットワークプログラミングの技術はデータの遠隔送信を実現するために米軍から来ています。.

人間が遠隔通信を実現する方法

# 電話
# ネットワークケーブル付きのビッグバットコンピューター
# ワイヤレスネットワークカード付きラップトップ

# 要約すると、最初の法則を結論付けることができます:リモート通信を実現するための最初の要件は:物理的な接続媒体
# 人と人とのコミュニケーションについて考えてみましょう。中国人は中国語を話し、外国人は外国語を話します。,
# それで、異なる国の人々の間でバリアフリーのコミュニケーションを実現したいのであれば、誰もが理解できる言語を指定する必要がありますか?>>>英語
# コンピュータ分野に戻ってください,コンピュータ間のリモート通信を実現するために、物理的な接続媒体に加えて、一連の公的な基準が必要ですか??この一連の標準は
# >>> OSI7層プロトコル(OSI7層モデルとも呼ばれます)

OSI 7層プロトコル(モデル)

# アプリケーション層
# プレゼンテーションレイヤー
# セッションレイヤー
# トランスポート層
# ネットワーク層
# データリンクレイヤー
# 物理接続層

# 一部の人々はそれを5つの層にグループ化します
# アプリケーション層
# トランスポート層
# ネットワーク層
# データリンクレイヤー
# 物理接続層
物理レイヤー#####

物理層の起源:前述のように、分離されたコンピューター間で一緒にプレイするには、コンピューターがインターネットに接続されている必要があります。つまり、コンピューターがネットワークを完成させる必要があります。

物理層機能:主に高低電圧(電気信号)を送信する回路特性に基づいて、高電圧は番号1に対応し、低電圧は番号0に対応します

# コンピュータ間の物理的な接続を実現し、送信されるデータはすべて010101バイナリです
# 電気信号の動作原理:高低のみポイント

ファイバー

ツイストペア

データリンクレイヤー#####

` データリンク層の起源:純粋な電気信号0と1は意味がありません。1つのグループの電気信号の数と各グループの意味を指定する必要があります。

データリンク層の機能:電気信号のグループ化方法を定義します

イーサネットプロトコル

当初、各企業は独自のグループ化方法を持っていましたが、後に統一された標準、つまりイーサネットプロトコルイーサネットを形成しました。

イーサネット規制

` 電気信号のグループは、「フレーム」と呼ばれるデータヒョウを形成します。

` 各データフレームは、ヘッダーとデータの2つの部分に分かれています。

Head Data
ヘッダー データ
# 頭に含まれるもの:(18バイトを修正)
 # 送信者/送信元アドレス、6バイト
	#受信者/ターゲットアドレス、6バイト
	#データタイプ、6バイト
    
# データに含まれる:(最短の長さは46バイト、最長の長さは1500バイトです。)
	#データパケットの特定の内容
# 頭の長さ+データ長=最短の長さは64バイト、最長の長さは1518バイトです。制限を超えると、フラグメントで送信されます。

Macアドレス

ヘッドに含まれる送信元アドレスと宛先アドレスの発信元:ethernetは、インターネットに接続されているすべてのデバイスにネットワークカードが必要であると規定しており、送信者と受信者のアドレスはネットワークカードのアドレス、つまりMacアドレスを指します。
Macアドレス:各ネットワークカードは、工場出荷時に世界で一意のMacアドレスで書き込まれます。長さは48桁のバイナリで、通常は12桁の16進数で表されます(最初の6桁はメーカー番号、最後の6桁はパイプラインです)。数)

放送

macアドレスを使用すると、同じネットワーク内の2つのホストが通信できます(一方のホストは、arpプロトコルを介してもう一方のホストのmacアドレスを取得します)
イーサネットは最も原始的な方法であるブロードキャスト通信を使用します。つまり、コンピュータ通信は基本的に轟音に依存します

# 1. バイナリデータのグループ化方法を指定します
# 2. インターネットに接続されたコンピューターである限り、ネットワークカードが必要であると規定されています。
# ネットワークカードには、世界で唯一の番号が刻印されています
# 各ネットワークカードは、工場出荷時に世界で一意のMacアドレスで書き込まれます
# 長さは48桁のバイナリで、通常は12桁の16進数で表されます(最初の6桁はメーカー番号、最後の6桁は組立ライン番号です)
# パイプネットワークカードに刻印されている番号はコンピューターと呼ばれています>>>Macアドレス
# —–>上記の2つの規制は、実際には「イーサネットプロトコル」です。

# イーサネットプロトコルに基づく通信:コミュニケーションは基本的にハウリングに依存します!!!短所:放送嵐
# スイッチ: 如果没有スイッチ,你的电脑就变成了马蜂窝,有了スイッチ吼,所有的电脑只需要一个网卡连接スイッチ,即可实现多台电脑之间物理连接
ネットワークレイヤー#####

ネットワーク層の起源:イーサネット、マックアドレス、ブロードキャストの伝送方式で、世界中のコンピューターが相互に通信できる問題は、世界中のインターネットが
互いに隔離された小さなローカルエリアネットワークで構成されており、すべての通信がイーサネットのブロードキャスト方式を使用している場合、マシンによって送信されたパケットは世界中で受信されます。
これは単に効率が悪いという問題だけでなく、災害になります

上図の結論:同じブロードキャストドメインに属しているコンピューターと属していないコンピューターを区別する方法を見つける必要があります。属している場合は、ブロードキャストで送信されます。そうでない場合は、ブロードキャストで送信されます。
ルーティング(異なるブロードキャストドメイン/サブネットへのデータパケットの配布)を使用すると、Macアドレスは区別できず、製造元にのみ関連します。
ネットワークレイヤー機能:異なるブロードキャストドメイン/サブネットを区別するために新しいアドレスのセットを導入します。このアドレスのセットはネットワークアドレスです

IPプロトコル:

IPアドレスは2つの部分に分かれています

注:純粋なIPアドレスセグメントはIPアドレスのタイプのみを識別し、ネットワーク部分またはホスト部分からIPが配置されているサブネットを識別することはできません。

例:172.16.10.1と172.16.10.2は、それらが同じサブネット内にあることを確認していません

サブネットマスク

いわゆる「サブネットマスク」は、サブネットの特性を示すパラメータです。これは、形式のIPアドレスと同等であり、32ビットのバイナリ番号でもあります。ネットワーク部分はすべて1で、ホスト部分はすべて0です。たとえば、IPアドレス172.16.10.1の場合、ネットワーク部分が最初の24桁で、ホスト部分が最後の8桁であることがわかっている場合、サブネットマスクは11111111.11111111.11111111.00000000で、10進数で255.255.255.0です。

「サブネットマスク」がわかれば、2つのIPアドレスが同じサブネット上にあるかどうかを判断できます。この方法では、2つのIPアドレスとサブネットマスク(両方の桁が1で、操作の結果が1、それ以外の場合は0)に対してAND演算を実行し、結果が同じかどうかを比較します。ネットワークでは、そうでなければそうではありません。

たとえば、既知のIPアドレス172.16.10.1と172.16.10.2のサブネットマスクは両方とも255.255.255.0です。それらは同じサブネット上にありますか?とサブネットマスクの両方が別々にANDされ、

172.16.10.1 :10101100.00010000.00001010.000000001

255255.255.255.0:11111111.11111111.11111111.00000000

AND演算のネットワークアドレス結果:10101100.00010000.00001010.000000001-> 172.16.10.0

172.16.10.2 :10101100.00010000.00001010.000000010

255255.255.255.0:11111111.11111111.11111111.00000000

AND演算のネットワークアドレス結果:10101100.00010000.00001010.000000001-> 172.16.10.0

結果は両方とも172.16.10.0であるため、同じサブネットにあります。

要約すると、IPプロトコルには2つの主要な機能があります。1つは各コンピューターにIPアドレスを割り当てることであり、もう1つは同じサブネット上にあるアドレスを判別することです。

ipパケット

ipデータパケットもヘッド部分とデータ部分に分割されており、ipパケット用に個別のフィールドを定義する必要はなく、イーサネットパケットのデータ部分に直接配置されます。

ヘッド:長さ20〜60バイト

データ:最大長は65,515バイトです。

イーサネットパケットの「データ」部分の長さはわずか1500バイトです。したがって、IPデータパケットが1500バイトを超える場合は、複数のイーサネットデータパケットに分割して個別に送信する必要があります。

イーサネットヘッダー ipヘッダー ipデータ

ARPプロトコル

arpプロトコルの起源:コンピュータ通信は基本的に轟音、つまりブロードキャストに依存しています。すべての上位層のパケットは、最後にイーサネットヘッダーでカプセル化してから、イーサネットプロトコルを介して送信する必要があります。イーサネットプロトコルについて話すとき、私たちは学びました。

通信はマックベースのブロードキャスト方式に基づいて実現されます。コンピュータがパッケージを送信すると、独自のマックを簡単に取得できます。ターゲットホストのマックを取得する方法は、arpプロトコルに合格する必要があります。

arpプロトコル機能:ブロードキャストモードでデータパケットを送信して、ターゲットホストのmacアドレスを取得します

プロトコル動作モード:各ホストIPは既知です

例:ホスト172.16.10.11/24訪問172.16.10.11/24

1つ:まず、IPアドレスとサブネットマスクで現在のサブネットを区別します

シーン パケットアドレス
同じサブネット ターゲットホストmac、ターゲットホストip
異なるサブネット ゲートウェイmac、ターゲットホストip

2:分析172.16.10.11/24と172.16.10.11/24が同じネットワーク内にある(同じネットワークでない場合、次の表のターゲットIPは172.16.10.1であり、ゲートウェイのMACはarpを介して取得されます)

ソースmac ターゲットmac ソースip ターゲットip データ部分
送信者ホスト 送信者mac FF:FF:FF:FF:FF:FF 172.16.10.10 / 24 172.16.10.11 / 24 データ

3:このパケットは、送信者が配置されているセルフネットワークでブロードキャスト方式で送信されます。すべてのホストがパケットを受信した後、パケットを開いて、ターゲットIPが自分のものであることを確認します。応答してMacを返します。

# すべてのコンピューターにIPアドレスが必要であることが規定されています
# IPアドレスの特性:点線の10進数
# より多くのコンピューターと互換性を持たせるために、ipv4とipv6の2つのバージョンがあります
# 一番小さい:0.0.0.0  
# 最大:255.255.255.255  
# IPプロトコルはLAN経由で送信できます
# ipアドレスは、インターネット上の一意のマシンを一意に識別できます。
# [ http://14.215.177.39/](http://14.215.177.39/)
トランスポートレイヤー(ポートプロトコル)#####

トランスポート層の起源:ネットワーク層のipは分子ネットワークの分割に役立ち、イーサネット層のmacはホストの検索に役立ちます。その後、全員がアプリケーションを使用します。QQ、Baofengyingyin、およびその他のアプリケーションをコンピューターで同時に開くことができます。プログラム、

次に、ipとmacを介して特定のホストを見つけました。このホスト上のアプリケーションを識別する方法、答えはポート、ポートはアプリケーションとネットワークカードに関連付けられた番号です。

トランスポート層機能:ポート間通信を確立します

補足:ポート範囲は0〜65535、0〜1023はシステム占有ポートです

tcpプロトコル:

信頼性の高い送信、TCPデータパケットには長さの制限がなく、理論的には無制限にすることができますが、ネットワークの効率を確保するために、通常、TCPデータパケットの長さはIPデータパケットの長さを超えないため、単一のTCPデータパケットを分割する必要はありません。

イーサネットヘッダー ipヘッダー tcpヘッダー データ

tcpメッセージ

tcp3ハンドシェイクと4ウェーブハンド

udpプロトコル:

信頼性の低い送信である「ヘッダー」部分の合計はわずか8バイトで、全長は65,535バイトを超えず、IPデータパケットに収まります。

イーサネットヘッダー ipヘッダー udpヘッダー データ
# TCP、UDPはポートに基づいて機能します!
# 実際、コンピューター間の通信は、実際にはコンピューター上のアプリケーションとアプリケーション間の通信です。
# 港(port):コンピュータ上のネットワーク通信に基づいて特定のアプリケーションを一意に識別します
# ポート範囲:0~~65535(動的割り当て)  
# 注:0~~1024は通常、オペレーティングシステムによって割り当てられたポート番号です。
# 通常の状況では、私たちが書くソフトウェアポート番号は8000以降に開始することをお勧めします
# フラスコフレームワークのデフォルトポート5000
# djangoフレームワークのデフォルトポート8000
# mysqlデータベースのデフォルトポートは3306です
# Redisデータベースのデフォルトポート6379
# 注意:ポート番号は、コンピューター上で同時に1つのアプリケーションのみが使用できます

# 小さな要約:  
# IPアドレス:世界でインターネットに接続されている一意のマシンを一意に識別します
# ポート番号:コンピューター上のアプリケーションを一意に識別します
# ip+port :世界のユニークなコンピューター上のアプリケーションを一意に識別できる

# 補足:  
# arpプロトコル:ipアドレスに従ってmacアドレスを解決します
アプリケーション層(HTTPプロトコル、FTPプロトコル)#####

アプリケーション層の起源:すべてのユーザーがアプリケーションを使用し、すべてがアプリケーション層で作業します。インターネットが開発され、誰もが独自のアプリケーションを開発できます。データにはさまざまな種類があり、データの編成を指定する必要があります。
アプリケーション層機能:アプリケーションのデータ形式を指定します。
例:TCPプロトコルは、Email、WWW、FTPなどのさまざまなプログラムのデータを転送できます。次に、電子メール、Webページ、およびFTPデータの形式を指定するさまざまなプロトコルが必要であり、これらのアプリケーションプロトコルは「アプリケーション層」を構成します。

TCP \ UDPプロトコル(ストリーミングプロトコル、信頼できるプロトコル)#####
# 3つのハンドシェイクと4つの波
# 接続を確立するための3方向ハンドシェイク
# 4回振って接続を切断します

# Tcp(ボイスチャット/ビデオチャット),高強度映画のオフラインキャッシュ\QQリモートコントロール
# 通信する前に接続を確立する必要があります
# 接続を占有します\信頼性のある(メッセージは失われません)\高リアルタイム\スロー

# UDP(メッセージを送る)-オンラインでビデオを再生する\QQメッセージを送る\WeChatメッセージ
# 接続を確立せずに通信できます
# 接続を占有しないでください\信頼できない\ネットワークが不安定なため、メッセージが失われます\速い
ネットワーク通信の実現#####

ネットワーク通信を実現するには、各ホストに4つの要素が必要です。

これらの4つの要素を取得するには2つの方法があります

  1. 静的取得

手動構成

  1. 動的取得

dhcpを通過する

イーサネットヘッダー ipヘッダー udpヘッダー dhcpパケット

(1)最初の「イーサネットヘッダー」は、送信者(マシン)のMACアドレスと受信者(DHCPサーバー)のMACアドレスを設定します。前者はローカルネットワークカードのMACアドレスであり、後者は現時点ではわかりません。ブロードキャストアドレスFF-FF-FF-FF-FF-FFを入力するだけです。

(2)後部の「IPヘッダー」に、送信者のIPアドレスと受信者のIPアドレスを設定します。現時点では、マシンは両方について認識していません。したがって、送信者のIPアドレスは0.0.0.0に設定され、受信者のIPアドレスは255.255.255.255に設定されます。

(3)最後の「UDPヘッダー」に、送信者のポートと受信者のポートを設定します。この部分はDHCPプロトコルで規定されており、送信側はポート68、受信側はポート67です。

データパケットが作成されたら、送信できます。イーサネットはブロードキャスト送信であり、同じサブネット上のすべてのコンピューターがこのパケットを受信しています。受信者のMACアドレスはFF-FF-FF-FF-FF-FFであるため、送信先が明確ではありません。したがって、このパケットを受信するすべてのコンピューターは、パケットのIPアドレスも分析して決定する必要があります。あなた自身のためではありません。送信者のIPアドレスが0.0.0.0で、受信者のIPアドレスが255.255.255.255であることがわかると、DHCPサーバーは「このパケットが私に送信された」ことを認識し、他のコンピューターはこのパケットを破棄できます。

次に、DHCPサーバーはこのパケットのデータコンテンツを読み取り、IPアドレスを割り当て、「DHCP応答」パケットを送り返します。この応答パケットの構造は類似しています。イーサネットヘッダーのMACアドレスは両当事者のネットワークカードアドレスであり、IPヘッダーのIPアドレスはDHCPサーバー(送信者)と255.255.255.255(受信者)のIPアドレス、UDPヘッダーです。ポートは67(送信者)と68(受信者)です。リクエスターに割り当てられたIPアドレスとネットワークの特定のパラメーターは、データセクションに含まれています。

新しく追加されたコンピューターはこの応答パケットを受信するため、自身のIPアドレス、サブネットマスク、ゲートウェイアドレス、DNSサーバーおよびその他のパラメーターを認識しています。

ネットワーク通信プロセス#####

ローカル買収

4.2 ブラウザを開いて、

Googleにアクセスするには、アドレスバーにURLを入力します:www.google.com。

dnsプロトコル(udpプロトコルに基づく)

13 Taigen dns:

A.root-servers.net198.41.0.4米国
B.root-servers.net192.228.79.201米国([IPv6](https://www.baidu.com/s?wd=IPv6&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1d9ryR4nhnsn1b3ujfYPAfk0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3ErH0YPW6snH0)もサポートされています)
C.root-servers.net192.33.4.12フランス
D.root-servers.net128.8.10.90米国
E.root-servers.net192.203.230.10米国
F.root-servers.net192.5.5.241米国([IPv6](https://www.baidu.com/s?wd=IPv6&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1d9ryR4nhnsn1b3ujfYPAfk0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3ErH0YPW6snH0)もサポートされています)
G.root-servers.net192.112.36.4米国
H.root-servers.net128.63.2.53米国([IPv6](https://www.baidu.com/s?wd=IPv6&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1d9ryR4nhnsn1b3ujfYPAfk0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3ErH0YPW6snH0)もサポートされています)
I.root-servers.net192.36.148.17スウェーデン
J.root-servers.net192.58.128.30米国
K.root-servers.net193.0.14.129 UK(IPv6もサポート)
L.root-servers.net198.32.64.12米国
M.root-servers.net202.12.27.33日本(IPv6もサポート)

ドメイン名の定義:[http://jingyan.baidu.com/article/1974b289a649daf4b1f774cb.html](http://jingyan.baidu.com/article/1974b289a649daf4b1f774cb.html)

トップレベルのドメイン名:.com、.net、.org、.cnなどは国際的なトップレベルのドメイン名です。現在のインターネットドメイン名システムによると、国際的なトップレベルのドメイン名は、カテゴリトップレベルドメイン(gTLD)と地理的トップレベルドメイン(ccTLD)の2つのカテゴリに分類されます。 )2種類。カテゴリトップレベルドメインは、「COM」、「NET」、「ORG」、「BIZ」、「INFO」などで終わるドメイン名であり、外国企業によって管理されています。トップレベルの地理的ドメイン名は、国または地域コードで終わるドメイン名です。たとえば、中国の場合は「CN」、英国の場合は「UK」です。地理的なトップレベルのドメイン名は、通常、各国または地域によって管理されます。

第2レベルのドメイン名:第2レベルのドメイン名は、最上位のドメイン名に基づく地理的なドメイン名です。親ドメイン名のサブドメインは、abc.comである親ドメイン名に類似しており、サブドメイン名はwww.abc.comまたは* .abc.comです。**一般的に、第2レベルのドメイン名は、alidiedie.comなどのドメイン名のレコードです。ドメイン名、www.alidiedie.comは、最も一般的に使用されるレコードの1つであり、これは通常、デフォルトで使用されますが、*。alidiedie.comなどのドメイン名はすべて第2レベルのalidiedie.comと呼ばれます。

ソケット(ソケットプログラミング)####

ソケットを確認する前に、5層の通信プロセスを確認しましょう。

しかし実際には、トランスポート層以降から始めて、オペレーティングシステムは、以下のさまざまなヘッダーカプセル化プロセスを完了するのに役立ちます。それらを1つずつ実行する必要がありますか? **番号! ****

ソケットはソケットとも呼ばれ、アプリケーション層とTCP / IPプロトコルスイート間の通信用のミドルウェアの抽象化層です。インターフェイスのセットです。設計モードでは、Socketは実際にはファサードモードであり、複雑なTCP / IPプロトコルファミリをSocketインターフェイスの背後に隠します。ユーザーにとっては、一連の単純なインターフェイスがすべてであり、Socketは指定されたものに準拠するようにデータを整理できます。プロトコル。異なるプロトコルを使用して通信する場合、異なるインターフェースを使用し、異なるプロトコルのさまざまな詳細を処理する必要があります。これにより、開発が難しくなり、ソフトウェアの拡張が容易になりません(会社の管理システムを開発するのと同じように)。 、アカウントの払い戻し、会議の予約、休暇のリクエストなどの機能は、システムに個別に書き込む必要はありませんが、各機能がどのように実装されているかを知らなくても、システム上の複数の機能インターフェイスに書き込む必要があります。そこで、UNIX BSDは、各プロトコルの通信の詳細を保護するソケットを発明しました。これにより、プログラマーはプロトコル自体に注意を払う必要がなくなり、ソケットによって提供されるインターフェイスを直接使用して、相互接続された異なるホストのプロセス間で通信します。これは、オペレーティングシステムが、基盤となるハードウェア機能を使用するシステム呼び出しを提供するようなものです。システム呼び出しを通じて、ディスクの読み取りと書き込み、およびメモリの管理を行うことなく、ディスク(ファイル操作)を便利に使用し、メモリを使用できます。ソケットは実際には同じものです。つまり、tcp / ipプロトコルの抽象化を提供し、外部への一連のインターフェイスを提供します。このインターフェイスを使用すると、tcp / ipプロトコルの機能を均一かつ便利に使用できます。

実際、あなたの観点からは、ソケットはモジュールです。モジュールに実装されているメソッドを呼び出すことにより、2つのプロセス間の接続と通信を確立します。 ipはインターネット上のホストの場所を識別するために使用され、portはこのマシン上のアプリケーションを識別するために使用されるため、ソケットをip + portと呼ぶ人もいます。したがって、アプリケーションを見つけるためにIPとポートを確立し、ソケットモジュールを使用してアプリケーションと通信するだけで済みます。

ソケットは「ソケット」とも呼ばれます。アプリケーションは通常、ネットワークに要求を送信するか、「ソケット」を介してネットワーク要求に応答するため、ホスト間またはコンピューターのプロセス間の通信が可能です。これは、複雑で醜いオペレーティングシステムに似ています。制御コンピュータハードウェアの操作は、統一されたシンプルなインターフェイスにパッケージ化されており、ユーザーはオペレーティングシステムの操作方法を学ぶだけで、コンピュータハードウェアを簡単かつ迅速に操作できます

ソケットの開発履歴と分類#####

ソケットは、1970年代にカリフォルニア大学バークレー校のUnixバージョンであるBSDUnixとして知られています。そのため、ソケットを「バークレーソケット」または「BSDソケット」と呼ぶことがあります。当初、ソケットは同じホスト上の複数のアプリケーション間の通信用に設計されていました。これは、プロセス間通信またはIPCとも呼ばれます。ソケットには、ファイルベースとネットワークベースの2種類(または2つのレースと呼ばれる)があります。

ファイルタイプに基づくソケットファミリ

ソケットファミリの名前:AF_UNIX

unixのすべてがファイルです。ファイルベースのソケットは、基になるファイルシステムを呼び出してデータをフェッチします。2つのソケットプロセスは同じマシンで実行され、同じファイルシステムにアクセスすることで間接的に通信できます。

ネットワークタイプに基づくソケットファミリ

ソケットファミリの名前:AF_INET

( ipv6で使用されるAF_INET6もあり、他にもいくつかのアドレスファミリがありますが、それらは特定のプラットフォームでのみ使用されるか、廃止されたか、ほとんど使用されないか、まったく実装されていません。その中で、AF_INETが最も広く使用されています。Pythonは多くのアドレスファミリをサポートしていますが、ネットワークプログラミングのみに関心があるため、ほとんどの場合AF_INETのみを使用します)

TCPとUDPの比較#####

TCP(Transmission Control Protocol)は、信頼性の高い接続指向のプロトコル(例:電話)、低い伝送効率、全二重通信(送信バッファーと受信バッファー)、およびバイトストリーム指向です。 TCPを使用するアプリケーション:Webブラウザー;ファイル転送プログラム。

UDP(User Datagram Protocol)は、信頼性が低く接続のないサービスであり、送信効率が高く(送信前の遅延が小さい)、1対1、1対多、多対1、多対多、パケット指向(データパケット)、混雑を抑えずにサービスを提供するように最善を尽くします。 UDPを使用するアプリケーション:ドメインネームシステム(DNS)、ビデオストリーミング、Voice over IP(VoIP)。

TCPプロトコル#####でのソケット

人生のシーン。友達に電話をかけたい場合は、まず番号をダイヤルすると、呼び出し音が聞こえた後、友達が電話に出ます。その後、あなたとあなたの友達が接続を確立し、あなたが話すことができます。通信が終了したら、電話を切って会話を終了します。人生のシーンは、これがどのように機能するかを説明しています。

サーバー側から始めましょう。サーバーは最初にソケットを初期化し、次にポートにバインドし、ポートをリッスンし、accept to blockを呼び出し、クライアントが接続するのを待ちます。このとき、クライアントがソケットを初期化してからサーバーに接続(接続)すると、接続が成功すると、クライアントとサーバー間の接続が確立されます。クライアントがデータ要求を送信し、サーバーが要求を受信して要求を処理してから、応答データをクライアントに送信し、クライアントがデータを読み取り、最後に接続を閉じて、対話が終了します。

以下では、socket()モジュール関数の使用法を紹介します

Pythonでは、socket()関数を使用してソケットを作成します。構文形式は次のとおりです。

socket.socket([family[,type[,proto]]])import socket
socket.socket(socket_family,socket_type,protocal=0)
 socket_家族はAFになることができます_UNIXまたはAF_INET。socket_タイプはSOCKにすることができます_STREAMまたはSOCK_DGRAM。プロトコルは一般的に満たされていません,デフォルト値は0です。

 tcpを取得する/ipソケット
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

udpを取得する/ipソケット
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

ソケットモジュールの属性が多すぎるためです。ここで例外を作りました'from module import *'ステートメント。使用する'from socket import *',ソケットモジュールのすべての属性を名前名に追加しました,これにより、コードを大幅に短縮できます。
例:tcpSock=socket(AF_INET, SOCK_STREAM)
サーバーソケット機能
s.bind()練る(ホスト,ポート番号)ソケットに
s.listen()TCPリスニングを開始します
s.accept()TCPクライアント接続を受動的に受け入れる,(ブロッキング)接続を待っています

クライアントソケット機能
s.connect()TCPサーバー接続を積極的に開始する
s.connect_ex()connect()機能の拡張バージョン,エラーが発生するとエラーコードが返されます,例外をスローする代わりに

公用ソケット機能
s.recv()TCPデータを受信する
s.send()TCPデータを送信する(送信するデータの量がバッファ領域の残りのスペースよりも多い場合に送信します,データが失われました,終了しません)
s.sendall()完全なTCPデータを送信する(本質は、ループで送信を呼び出すことです,送信するデータの量がそれ自体のバッファーの残りのスペースよりも多い場合はsendall,データの損失なし,送信されるまでループで送信を呼び出す)
s.recvfrom()UDPデータを受信する
s.sendto()UDPデータを送信する
s.getpeername()現在のソケットに接続されているリモートエンドのアドレス
s.getsockname()現在のソケットのアドレス
s.getsockopt()指定されたソケットのパラメータを返します
s.setsockopt()指定したソケットのパラメータを設定します
s.close()ソケットを閉じる

ロック指向のソケット方式
s.setblocking()ソケットのブロッキングモードと非ブロッキングモードを設定します
s.settimeout()ソケット操作をブロックするためのタイムアウト期間を設定します
s.gettimeout()ソケット操作をブロックするためのタイムアウト期間を取得します

ファイル指向ソケットの関数
s.fileno()ソケットのファイル記述子
s.makefile()ソケットに関連するファイルを作成します

パラメータ

# family:ソケットファミリーはAFを作ることができます_UNIXまたはFA_INET
# type:ソケットタイプは、接続指向または非接続雰囲気のSOCKに基づくことができます。_STREAMまたはSOCK_DGRAM.
# protocol:通常、デフォルトは0です。.

ソケットオブジェクト(組み込み)メソッド

機能 説明
サーバー側ソケット
s.bind() アドレス(ホスト、ポート)をソケットにバインドします。AF_INETでは、アドレスはタプル(ホスト、ポート)の形式で表されます。
s.listen() TCPリスニングを開始します。バックログは、接続が拒否される前にオペレーティングシステムがハングできる接続の最大数を指定します。値は少なくとも1であり、ほとんどのアプリケーションは5に設定します。
s.accept() TCPクライアント接続を受動的に受け入れ、接続が到着するのを(ブロック)待機します
クライアントソケット
s.connect() TCPサーバー接続をアクティブに開始します。一般的なアドレス形式はタプル(ホスト名、ポート)です。接続に失敗すると、socket.errorが返されます。
s.connect_ex() connect()関数の拡張バージョンは、エラーが発生すると、例外をスローする代わりにエラーコードを返します
公共用のソケット機能
s.recv() TCPデータを受信します。データは文字列として返されます。bufsizeは、受信するデータの最大量を指定します。フラグはメッセージに関するその他の情報を提供し、通常は無視できます。
s.send() TCPデータを送信し、接続されたソケットに文字列でデータを送信します。戻り値は送信されるバイト数であり、文字列のバイトサイズよりも小さい場合があります。
s.sendall() TCPデータを完全に送信し、TCPデータを完全に送信します。接続されたソケットに文字列でデータを送信しますが、戻る前にすべてのデータを送信してみてください。成功した場合はNoneを返し、失敗した場合は例外をスローします。
s.recvfrom() recv()と同様にUDPデータを受信しますが、戻り値は(data、address)です。ここで、dataは受信データを含む文字列であり、addressはデータを送信するためのソケットのアドレスです。
s.sendto() UDPデータを送信し、データをソケットに送信します。アドレスは、リモートアドレスを指定する(ipaddr、port)形式のタプルです。戻り値は、送信されたバイト数です。
s.close() ソケットを閉じる
s.getpeername() 接続されたソケットのリモートアドレスを返します。戻り値は通常、タプル(ipaddr、port)です。
s.getsockname() ソケット自体のアドレスを返します。通常、タプル(ipaddr、port)
s.setsockopt(level、optname、value) 指定されたソケットオプションの値を設定します。
s.getsockopt(level、optname [.buflen]) ソケットオプションの値を返します。
s.settimeout(timeout) ソケット操作のタイムアウト期間を設定します。タイムアウトは秒単位の浮動小数点数です。 Noneの値は、タイムアウト期間がないことを意味します。通常、タイムアウト期間は、ソケットが作成された直後に設定する必要があります。これは、ソケットが接続操作(connect()など)に使用される可能性があるためです
s.gettimeout() 現在のタイムアウト期間の値を秒単位で返します。タイムアウト期間が設定されていない場合は、Noneを返します。
s.fileno() ソケットのファイル記述子を返します。
s.setblocking(flag) flagが0の場合、ソケットを非ブロッキングモードに設定し、そうでない場合は、ソケットをブロッキングモード(デフォルト値)に設定します。非ブロッキングモードでは、recv()の呼び出しでデータが見つからない場合、またはsend()の呼び出しでデータをすぐに送信できない場合、socket.error例外が発生します。
s.makefile() ソケットに関連するファイルを作成する

Example1

# server.py
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))

# 他の人が私とつながるのを待っています
sk.listen()
# 顧客が私をリンクするのを待っています,そして、リンクアドレスがあります
conn,addr = sk.accept()print(conn,"CCCCCCCCCOOO")print(addr,"IPAIP")
conn.send(b'hello')
msg = conn.recv(1024)print(msg)
# 最大1024バイトのデータを受信します
conn.recv(1024)
conn.close()
# 彼の電源を切り、他の人にリンクさせないでください
sk.close()

# client.py
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
msg = sk.recv(1024)print(msg)
sk.send(b'byebyte')
sk.close()

Example2

サーバ

# ソケットモジュールのソケット関数を使用してソケットオブジェクトを作成し、ソケットオブジェクトは他の関数を呼び出すことでソケットサービスを設定できます。.
# これでバインドを渡すことができます(hostname,port)サービスのポートを指定する機能(港)
# 次に、ソケットオブジェクトのacoeplメソッドを呼び出します。このメソッドは、クライアントの接続を待機し、クライアントが接続されていることを示す接続オブジェクトを返します。
#! /usr/bin/python3
# ファイル名:サーバー.py

# ソケットとsysモジュールをインポートします
import socket
import sys

# ソケットオブジェクトを作成する
serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# マシンのホスト名を取得します
host = socket.gethostname()
port =9999

# バインディングポート番号
serversocket.bind((host,port))

# 接続の最大数を設定し、超過後にキューに入れます
serversocket.listen(5)while True:
  # クライアント接続を確立する
 clientsocket,addr = serversocket.accept()print("接続アドレス: %s"%str(addr))
 msg='YouMenDemoへようこそ!'+"\r\n"
 clientsocket.send(msg.encode('utf-8'))
 clientsocket.close()

クライアント

# 次に、上記で作成したサービスに接続するための単純なクライアントインスタンスを作成します。ポート番号は9999です。
# socket.connect(hostname,port)ホストがホストホストでポートがポートであるサービスプロバイダーへのTCP接続を開く方法。
# 接続後、サーバーからデータを取得できます。操作が完了したら、接続を閉じる必要があることを忘れないでください。.
#! /usr/bin/python3
# ファイル名:クライアント.py
import socket
import sys

# ソケットオブジェクトを作成する
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# ローカルホスト名を取得する
host = socket.gethostname()

# ポート番号を設定する
port =9999

# サービスに接続し、ホストとポートを指定します
s.connect((host,port))

# 1024バイト未満のデータを受け入れる
msg = s.recv(1024)

s.close()print(msg.decode('utf-8'))

` ここで、2つの端末を開いてserver.pyファイルを実行し、もう1つの端末でclient.pyファイルを実行すると、次のように表示されます。

# YouMenDemoへようこそ!

# 同時に最初のターミナルを開くと、次の情報出力が表示されます:
# 接続アドレス:('172.19.0.2',51157)

Example3

TCPとマルチクライアント通信

# サーバ側
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9005))
sk.listen()while True:
 conn,addr = sk.accept()print("conn :",conn)while True:
  send_msg =input('>>>')if send_msg.upper()=='Q':break
  conn.send(send_msg.encode('utf-8'))
  msg = conn.recv(1024).decode('utf-8')if msg.upper()=='Q':breakprint(msg)
 conn.close()
sk.close()

# クライアント側
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9005))while True:
 msg = sk.recv(1024)
 msg2 = msg.decode('utf-8')if msg2.upper()=='Q':breakprint(msg,msg2)
 send_msg =input('>>>')if send_msg.upper()=='Q':break
 sk.send(send_msg.encode('utf-8'))

sk.close()
Pythonインターネットモジュール#####

Pythonネットワークプログラミングのいくつかの重要なモジュールを以下に示します

プロトコル 機能使用 ポート番号 Pythonモジュール
HTTP Webアクセス 80 httplib、urllib、xmlrpclib
NNTP 一般に「投稿」として知られるニュース記事を読んで投稿する 119 nntplib
FTP ファイル転送 20 ftplib、urllib
SMTP メールを送信 25 smtplib
POP3 メールの受信 110 poplib
IMAP4 メールを受け取る 143 imaplib
Telnet コマンドライン 23 telnetlib
Gopher 情報検索 70 gopherlib、urllib

例2 **** TCPサーバー****サーバー構造

tcps =socket() #サーバーソケットを作成する
tcps.bind()      #アドレスをソケットにバインドします
tcps.listen()      #リンクを監視する
while True:      #サーバーの無限ループ
 tcpc = tcps.accept() #クライアントリンクを受け入れる
 while True:         #通信ループ
  tcpc.recv()/tcpc.send() #対話(送受信)
 tcpc.close()    #クライアントソケットを閉じる
tcps.close()        #サーバーソケットを閉じる(オプション)

タイムスタンプサーバーインスタンス

#! /usr/bin/python3
# - *- coding:utf-8-*-from socket import*import time
COD ='utf-8'
HOST ='192.168.164.141' #ホストIP
PORT =21566 #ソフトウェアポート番号
BUFSIZ =1024
ADDR =(HOST, PORT)
SIZE =10 
tcpS =socket(AF_INET, SOCK_STREAM) #ソケットオブジェクトを作成する
tcpS.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #ソケット構成を追加し、IPとポートを再利用します
tcpS.bind(ADDR) #バインドIPポート番号
tcpS.listen(SIZE)  #リンクの最大数を設定します
while True:print("サーバーが起動し、クライアント接続をリッスンします")
 conn, addr = tcpS.accept()print("リンクされたクライアント", addr)while True:try:
   data = conn.recv(BUFSIZ) #リンクされた顧客から送信されたメッセージを読む
  except Exception:print("切断されたクライアント", addr)breakprint("クライアントが送信するもの:",data.decode(COD))if not data:break
  msg = time.strftime("%Y-%m-%d %X") #構造化されたイベントスタンプを取得する
  msg1 ='[%s]:%s'%(msg, data.decode(COD))
  conn.send(msg1.encode(COD)) #リンクされたクライアントにメッセージを送信する
 conn.close() #クライアントリンクを閉じる
tcpS.closel()

TCPクライアントクライアント構造*

tcpc =socket()    #クライアントソケットを作成する
tcpc.connect()    #サーバーに接続してみてください
while True:        #通信ループ
 tcpc.send()/tcpc.recv()    #対話(送信/受け取る)
tcpc.close()      #クライアントソケットを閉じる

タイムスタンプクライアントインスタンス

#! /usr/bin/python3
# - *- coding:utf-8-*-from socket import*from time import ctime
HOST ='192.168.164.141' #サーバーIP
PORT =21566 #サーバーポート番号
BUFSIZ =1024
ADDR =(HOST, PORT)
tcpCliSock =socket(AF_INET, SOCK_STREAM) #ソケットオブジェクトを作成する
tcpCliSock.connect(ADDR) #サーバーに接続する
while True:
 data =input('>>').strip()if not data:break
 tcpCliSock.send(data.encode('utf-8')) #メッセージを送る
 data = tcpCliSock.recv(BUFSIZ) #メッセージを読む
 if not data:breakprint(data.decode('utf-8'))
tcpCliSock.close() #クライアントを閉じる
スティッキーパッケージ現象#####

` パッケージの貼り付けについて説明する前に、ソケットバッファの問題を見てみましょう。

各ソケットが作成された後、入力バッファーと出力バッファーの2つのバッファーが割り当てられます。

write()/send()すぐにネットワークにデータを送信するのではなく、最初にデータをバッファに書き込み、次にTCPプロトコルによってバッファからターゲットマシンにデータを送信します。データがバッファに書き込まれると、ターゲットマシンに到達したか、ネットワークに送信されたかに関係なく、関数は正常に戻ることができます。これらはTCPプロトコルが担当します。

TCPプロトコルは書き込みに依存しません()/send()機能、データはバッファに書き込まれるとすぐにネットワークに送信される場合もあれば、バッファにバックログされ続ける場合もあります。複数回書き込まれたデータは、現在のネットワークの状況と現在のスレッドがアイドル状態であるかどうかに応じて、一度にネットワークに送信されます。多くの要因はプログラマーによって制御されていません。

read()/recv()同じことが関数にも当てはまります。関数は、ネットワークから直接ではなく、入力バッファーからデータを読み取ります。

これらの私/Oバッファの特性は、次のように並べ替えることができます。

1. I/Oバッファは各TCPソケットに個別に存在します。
2. I/Oバッファーは、ソケットの作成時に自動的に生成されます。
3. ソケットが閉じていても、出力バッファに残っているデータは送信され続けます。
4. ソケットを閉じると、入力バッファーのデータが失われます。

入力バッファと出力バッファのデフォルトサイズは通常8Kで、getsockoptを介して渡すことができます。()機能獲得:

1. unsigned optVal;2.int optLen =sizeof(int);3.getsockopt(servSock, SOL_SOCKET, SO_SNDBUF,(char*)&optVal,&optLen);4.printf("Buffer length: %d\n", optVal);

ソケットバッファの説明

ソケットバッファ領域の詳細な説明:
    
送信側は1つのKと1つのKでデータを送信でき、受信側のアプリケーションは2つのKと2つのKでデータを引き出すことができます。もちろん、一度に3Kまたは6Kのデータを引き出すことも、一度に数バイトのデータだけで引き出すこともできます。言い換えると、アプリケーションから見たデータは全体、つまりストリームであり、メッセージ内の何バイトがアプリケーションから見えないので、TCPプロトコルはストリーム指向のプロトコルであり、これも簡単です。スティッキーパッケージの問題の理由。 UDPはメッセージ指向のプロトコルです。各UDPセグメントはメッセージです。アプリケーションはメッセージ単位でデータを抽出する必要があり、一度に1バイトのデータを抽出することはできません。これはTCPとは大きく異なります。メッセージを定義する方法は?相手が一気に書いていると考えられます/送信データはメッセージです。相手がメッセージを送信すると、最下層がどのように断片化されていても、TCPプロトコル層がメッセージ全体を構成するデータセグメントを並べ替えてからカーネルバッファに表示することを理解する必要があります。

たとえば、tcpベースのソケットクライアントはファイルをサーバーにアップロードします。送信するとき、ファイルのコンテンツはセグメントごとにバイトストリームで送信されます。受信者がそれを見るとき、ファイルのバイトストリームがどこから始まるかはわかりません。どこで終わりますか

いわゆるスティッキーパケットの問題は、主に、受信者がメッセージ間の境界と、一度に抽出されるデータのバイト数を知らないという事実によって引き起こされます。

また、送信者によるスティッキーパケットはTCPプロトコル自体によるものであり、TCPの伝送効率を上げるために、送信者はTCPセグメントを送信する前に十分なデータを収集する必要があります。連続して数回送信する必要のあるデータが非常に小さい場合、通常、TCPは最適化アルゴリズムに従ってこれらのデータをTCPセグメントに合成し、1回送信して、受信者がスティッキーパケットデータを受信するようにします。

TCP(トランスポート制御プロトコル)は接続指向およびストリーム指向であり、信頼性の高いサービスを提供します。受信側と送信側(クライアントとサーバー)の両方にソケットのペアが必要です。したがって、送信者は、受信者に複数のパケットをより効果的に相手に送信するために、最適化方法(Nagleアルゴリズム)を使用します。間隔が短くデータ量が少ない複数のデータを1つの大きなデータブロックに結合してから、パケット化します。このように、受信側を区別することは困難であり、科学的な開梱メカニズムを提供する必要があります。つまり、フロー指向の通信にはメッセージ保護の境界がありません。
UDP(ユーザーデータグラムプロトコル、ユーザーデータグラムプロトコル)は、接続がなく、メッセージ指向であり、高効率のサービスを提供します。ブロックマージ最適化アルゴリズムを使用しません、,UDPは1対多モードをサポートしているため、受信側のskbuff(ソケットバッファ)は、到着するすべてのUDPパケットを記録するチェーン構造を採用しています。各UDPパケットには、メッセージヘッダー(メッセージの送信元アドレス、ポート、その他の情報)があります。このように、受信側では、それらを区別するのは簡単です。つまり、メッセージ指向の通信にはメッセージ保護の境界があります。
TCPはデータフローに基づいているため、送受信されるメッセージを空にすることはできません。これには、プログラムがスタックしないように、クライアントとサーバーの両方に空のメッセージ処理メカニズムを追加する必要があります。一方、udpは、入力した場合でもデータグラムに基づいています。空のコンテンツ(直接入力)、空のメッセージではありません。udpプロトコルはメッセージヘッダーのカプセル化に役立ちます。実験は省略されています。
udpのrecvfromがブロックされています、recvfrom(x)Sendinto(y),xバイトのデータを受信すると、完了です。,yの場合>xデータが失われます。つまり、udpはパケットにまったく付着しませんが、データが失われ、信頼性が低くなります。

TCPプロトコルデータが失われることはありません。パケットが受信されない場合、次に受信されたときに、最後の受信を継続します。ACKを受信すると、自身の側は常にバッファの内容をクリアします。データは信頼できますが、パッケージに固執します。

TCPだけがパケットを貼り付ける現象があり、UDPはパケットに貼り付くことはありません

# TCPプロトコルには複数のメッセージの間に境界がなく、最適化アルゴリズムが多数あるため、TCPプロトコルにのみ表示されます。.

# 2つのケースがバッグにくっつきます:
# 送信者:受信者がバッファ内のパケットを時間内に受信しなかったため、複数のパケットが受け入れられました(クライアントはデータの一部を送信し、サーバーはその一部のみを受信しました,サーバーが次回データを受信したときでも、バッファから残ったデータを取得してスティッキーパケットを生成します)

# 受信終了:送信者は、送信する前にバッファがいっぱいになるのを待つ必要があり、スティッキーパケットが発生します(データを送信する時間間隔は非常に短く、データも非常に小さいです。)
UDPプロトコル#####

データグラムプロトコル

# 1. udpプロトコルクライアントは空の送信を許可します
# 2. udpプロトコルはパッケージに固執しません
# 3. udpプロトコルサーバーが存在しない場合でも、クライアントはエラーを報告しません

Example1

# Socket_Server_UDP.py
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)

server =('127.0.0.1',8089)while True:
 msg =input('>>>')if msg.upper()=='Q':break
 sk.sendto(b'ip,port,server',server)
 msg = sk.recv(1024)if msg.upper()=='Q':breakprint(msg)
# Socket_Client_UDP.py
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',8089))while True:
 msg,addr = sk.recvfrom(1024)print(msg)
 msg=input(">>>")
 sk.sendto(msg.encode('utf-8'),addr)

Example2

#! /usr/bin/env python3
# - *- coding:utf-8-*-

# サーバ
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8000))

msg,addr=server.recvfrom(1024)print(msg.decode('utf-8'))
server.send(b'hello',addr)

server.close()
#! /usr/bin/env python3
#- *- coding:utf-8-*-

# クライアント
import socket

client=socket.socket(type=socket.SOCK_DGRAM)
server_addr=('127.0.0.1',8000)

client.sendto(b'hello server baby!',server_addr)
msg,addr=client.recvfrom(1024)print(msg,addr)
"""
# udp機能>>>リンクなし,テキストメッセージを送信するのと似ています。相手がそれを気に入っているかどうかは関係ありません。
# サーバーの電源がオフの場合でも、クライアントは起動時にデータを送信できます。サーバーが受信できるかどうかを考慮する必要がないため
"""
# udpプロトコルにスティッキーパケットの問題があるかどうかを確認します
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))print(server.recvfrom(1024))print(server.recvfrom(1024))print(server.recvfrom(1024))import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr =('127.0.0.1',8080)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)

UDPにQQの簡略版を提供する

#! /usr/bin/env python3
# - *- coding:utf-8-*-

# サーバ
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8000))while True:
 msg,addr=server.recvfrom(1024)print(addr)print(msg.decode('utf-8'))
 info=input('>>>:').encode('utf-8')
 server.sendto(info,addr)

server.close()
#! /usr/bin/env python3
#- *- coding:utf-8-*-

# クライアント
import socket

client=socket.socket(type=socket.SOCK_DGRAM)
server_addr=('127.0.0.1',8000)while True:
 info=input('>>>:')
 info=('クライアント1からのメッセージ:%s'%info).encode('utf-8')

 client.sendto(info,server_addr)
 msg,addr=client.recvfrom(1024)print(msg.decode('utf-8'),addr)

client.close()

総括する:

TCPプロトコルは呼び出しに似ています
UDPプロトコルは、[SMS](https://cloud.tencent.com/product/sms?from=10680)の送信に似ています

TCP完全ファイルアップロード#####

server.py

import socket
import subprocess
import json
import struct
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

phone.bind(('127.0.0.1',8001))

phone.listen(5)
file_positon = r'd:\アップロードダウンロード'

conn, client_addr = phone.accept()

# # 1 、固定4バイトの受信
ret = conn.recv(4)
#
# 2, structモジュールを使用してretをheadに戻します_dic_バイト単位の合計バイト数。
head_dic_bytes_size = struct.unpack('i',ret)[0]
#
# 3, 頭を受け取る_dic_バイトデータ。
head_dic_bytes = conn.recv(head_dic_bytes_size)

# 4, 頭_dic_バイトはjson文字列形式にデコードされます。
head_dic_json = head_dic_bytes.decode('utf-8')

# 5, json文字列を辞書モードに復元します。
head_dic = json.loads(head_dic_json)

file_path = os.path.join(file_positon,head_dic['file_name'])withopen(file_path,mode='wb')as f1:
 data_size =0while data_size < head_dic['file_size']:
  data = conn.recv(1024)
  f1.write(data)
  data_size +=len(data)
    

conn.close()
phone.close()

client.py

import socket
import struct
import json
import os
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #電話を購入する

phone.connect(('127.0.0.1',8001))  #クライアントとの接続を確立し、ダイヤルします

# 1 ファイルを作成する_info
file_info ={'file_path': r'D:\lnh.python\pyproject\PythonReview\ネットワークプログラミング\08ファイルのアップロードとダウンロード\低バージョン\aaa.mp4','file_name':'aaa.mp4','file_size': None,}
# 2 ファイルサイズの取得と設定
file_info['file_size']= os.path.getsize(file_info['file_path'])

# 2 、jsonを使用して頭を変更します_文字列にdic
head_dic_json = json.dumps(file_info)

# 3, 頭_dic_jsonをバイトに
head_dic_bytes = head_dic_json.encode('utf-8')

# 4 、 頭_dic_バイトのサイズは固定の4バイトに変換されます。
ret = struct.pack('i',len(head_dic_bytes))  #4バイトを修正

# 5, 固定4バイトを送信
phone.send(ret)

# 6 頭を送る_dic_bytes
phone.send(head_dic_bytes)

# ファイルを送信:
withopen(file_info['file_path'],mode='rb')as f1:
    
 data_size =0while data_size < file_info['file_size']:
 # f1.read()すべてを読み上げることも、すべてを送信することもできないため、送信が大きすぎると問題が発生します。念のため、毎回送信してください。(1024バイト)
  every_data = f1.read(1024)
  data_size +=len(every_data)
  phone.send(every_data)
        
phone.close()

文書の合法性を確認する

server.py

import os
import socket
import hashlib

secret_key = b'alex_sb'
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()

conn,addr = sk.accept()
# ランダムな文字列を作成する
rand = os.urandom(32)
# ランダムな文字列を送信する
conn.send(rand)

# 送信された文字列によると+要約のための秘密の鍵
sha = hashlib.sha1(secret_key)
sha.update(rand)
res = sha.hexdigest()

# クライアントから要約結果を受け取るのを待っています
res_client = conn.recv(1024).decode('utf-8')
# 比較する
if res_client == res:print('正当なクライアントです')
 # 一貫している場合,それは正当なクライアントです
 # そして続けることができます
 conn.send(b'hello')else:
 conn.close()
 # 一貫性がない場合,接続はすぐに閉じる必要があります

client.py

import socket
import hashlib

secret_key = b'alex_sb979'
sk = socket.socket()
sk.connect(('127.0.0.1',9001))

# クライアントから送信されたランダムな文字列を受信します
rand = sk.recv(32)
# 送信された文字列によると+要約のための秘密鍵
sha = hashlib.sha1(secret_key)
sha.update(rand)
res = sha.hexdigest()
# 要約結果はサーバーに返送されます
sk.send(res.encode('utf-8'))
# サーバーとの通信を続行します
msg = sk.recv(1024)print(msg)

Socketserverは同時実行性を実現します####

なぜsocketserverを使用するのですか?以前に作成したtcpプロトコルのソケットは、一度に1つのクライアントとしか通信できませんか?socketserverを使用すると、複数のクライアントと通信できます。これは、ソケットに基づくカプセル化のレイヤーであり、最下層が引き続きソケットと呼ばれることを意味します。py2.7では、SocketServerと呼ばれ、py3で大文字と小文字の2つのSを意味します。後で作成するFTPジョブでは、同時実行性を実現する必要があります。つまり、複数のクライアントと同時に通信でき、複数のユーザーが同時にアップロードおよびダウンロードできます。
それでは、最初にソケットサーバーの使用方法を見てから、分析してみましょう。最初に次のコードを見てください。

import socketserver  #インポートモジュール

classMyServer(socketserver.BaseRequestHandler):   #クラス名は任意に定義されますが、socketserverを継承する必要があります.BaseRequestHandlerクラス
    
 def handle(self):  #ハンドルメソッド、固定名を書く
  while1:
   # self.リクエストはconnパイプラインと同等です
   from_client_data = self.request.recv(1024).decode('utf-8')print(from_client_data)
   to_client_data =input('サーバーは次の情報を返します。').strip()
   self.request.send(to_client_data)if __name__ =='__main__':
 ip_port =('127.0.0.1',8080)
 # socketserver.TCPServer.allow_reuse_address = True  #ポートの再利用を許可する
 server = socketserver.ThreadingTCPServer(ip_port,MyServer)
 # ソケットサーバーへ.ThreadingTCPServerクラスは、オブジェクトをインスタンス化し、それ自体で定義されたIPアドレス、ポート番号、およびクラス名を渡し、オブジェクトを返します。
 server.serve_forever() #オブジェクト実行サーブ_永遠の方法、サーバーを開く

特定のプロセス分析:

# ソケットサーバーモジュールでは、実際には2つのことが行われます。1。1つはリンクを周期的に確立する部分であり、各クライアントリンクは正常に接続できます。2。通信サイクルの一部、つまり各クライアントが正常に接続された後、クライアントと周期的に通信するため。
# コードを見てください:サーバー=socketserver.ThreadingTCPServer(('127.0.0.1',8090),MyServer)

# オブジェクト指向の継承を覚えていますか?さあ、誰もがソースコードを見ようとします:

# 属性を見つける順序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer

# サーバーを取得するためにインスタンス化し、最初にThreadMinxInを探します__init__メソッド、initメソッドがないことがわかった後、クラスThreadingTCPServerを見つけます__init__,TCPServerで見つかり、内部にソケットオブジェクトを作成してから、サーバーを実行します_バインド(バインドと同等),server_アクティブ(クリックしてリッスンが実行されるかどうかを確認します)

# サーバーの下でサーブを見つける_forever,BaseServerで見つかり、selfを実行します._handle_request_noblock()、メソッドはBaseServerにもあります

# 自己実行._handle_request_noblock()そして、リクエストを実行します, client_address = self.get_request()(TCPServerでは自己です.socket.accept()),然后自己実行.process_request(request, client_address)

# ThreadingMixInでプロセスを見つける_リクエストし、マルチスレッドを開いて同時実行性を処理してから、プロセスを実行します_request_スレッド、自己実行.finish_request(request, client_address)

# 上記の4つの部分は、リンクサイクルを完了します。この部分は、通信部分の処理を開始し、BaseServerで終了を見つけます。_request,独自に定義したクラスのインスタンス化をトリガーし、検索に移動します__init__メソッド、および自分で定義したクラスにはこのメソッドがない場合は、その親クラスであるBaseRequestHandlerに移動して検索します....

# ソースコード分析の要約:

# 自分で定義したクラスのtcpソケットサーバーに基づく

  self.サーバーはソケットオブジェクトです
  self.リクエストはリンクです
  self.client_addressはクライアントアドレスです
定義された独自のクラスのudpソケットサーバーに基づく

  self.リクエストはタプルです(最初の要素はクライアントから送信されたデータで、2番目の部分はサーバーのudpソケットオブジェクトです)。(b'adsf',<socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1',8080)>)
  self.client_addressはクライアントアドレスです
```![]( https://img2020.cnblogs.com/blog/1871335/202005/1871335-20200517124446986-1187051722.png)

Recommended Posts

12.Python3でのネットワークプログラミング
Pythonネットワークプログラミング
pythonの関数
03.Pythonエントリの演算子
Pythonの結合関数
pythonでステートメントを印刷する
詳細なPythonIOプログラミング
PythonGUIインターフェイスプログラミング
Pythonでの同時リクエスト
Ubuntuにpythonをインストールする
Pythonでのコンテキスト管理
pythonの算術演算子
pythonでguiを書く
PythonでのMongoDBの使用
PythonのStr文字列
Pythonでの計算ジオメトリ
Pythonでの同時リクエスト(パート2)
Python機能プログラミングについて話す
Pythonのタプルの添え字
Pythonでの継承について話す
Python3.9の注目すべき更新ポイント
PythonプログラミングPycharm高速学習
GooglePythonプログラミングスタイルガイド
一般的に使用されるPython3スクリプトプログラミング.md
Pythonオブジェクト指向プログラミングの分析
XTUプログラミングPythonトレーニング3
Pythonアプリケーションを3分でコンテナ化
ブラックハットプログラミングアプリケーションPython2
pythonのイントロスペクションとは何ですか
pythonのオブジェクト指向とは何ですか
Pythonのジェネレーターとイテレーター
virtualboxのCentosネットワーク設定
Pythonで文字列について話す
pythonでのwheelの使用法
Pythonの対数法の要約
Python開発でのパンダの使用
pythonでnohupコマンド命令を使用する
pythonのリスト内包表記とは何ですか
pythonに関数のオーバーロードはありますか
PythonでNumpyを使い始める
詳細な並べ替えアルゴリズム(Pythonで実装)
pythonコードでラップする方法
Pythonでのrc1の意味
pythonの一般的なエラーと解決策
Python開発でのnumpyの使用
pythonのdefは何をしますか
Python1のブラックハットプログラミングアプリケーション
Pythonで括弧を省略する方法
Pythonでの辞書の詳細な使用法
pythonでのosパッケージの使用
Pythonでのガベージコレクションについて学ぶ
pythonでクラスを書く方法
pythonで数値をフィルタリングする方法
Pythonの数字は何ですか?
PythonでExcelを読む方法
Pythonにはいくつかのキーワードがあります
Pythonのすべてがオブジェクトです
pythonでエラーを表示する方法
npはpythonで何をしますか
pythonでreturnを書く方法
Pythonのモジュールについて話す