【GO言語基盤】GOネットワークプログラミング、TCP / IPモデルの実現(10)

ネットワークプログラミング

  1. TCPソケットプログラミングはネットワークプログラミングの主流です。最下層がTcp / ipプロトコルに基づいているため、Tcpソケットプログラミングと呼ばれます。
  2. b / s構造のhttpプログラミングの場合、ブラウザーを使用してサーバーにアクセスするときは、httpプロトコルを使用しますが、httpの最下層は引き続きtcpソケットで実装されます。

プロトコル(tcp / ip)

TCP / IP(Transmission Control Protocol / Internet Protocol)の略で、中国語の翻訳はTransmission Control Protocol / Internet Protocolと呼ばれ、Network Communication Protocolとも呼ばれます。このプロトコルは、インターネットの最も基本的なプロトコルであり、インターネットの基盤です。国際インターネットネットワーク。簡単に言えば、ネットワーク層のIPプロトコルとトランスポート層のTCPプロトコルで構成されています。

OSI参照モデル(理論)

ここに画像の説明を挿入

  • アプリケーション層:OSI参照モデルでユーザーに最も近い層は、コンピューターユーザーにアプリケーションインターフェイスを提供し、ユーザーにさまざまなネットワークサービスを直接提供することです。一般的なアプリケーション層ネットワークサービスプロトコルは、HTTP、HTTPS、FTP、POP3、SMTPなどです。

  • プレゼンテーション層:プレゼンテーション層は、あるシステムのアプリケーション層によって送信されたデータが別のシステムのアプリケーション層によって認識されることを保証するために、アプリケーション層データのさまざまなコーディングおよび変換機能を提供します。必要に応じて、このレイヤーは、コンピューター内の複数のデータ形式を通信で使用される標準表現に変換するための標準表現を提供できます。データの圧縮と暗号化も、プレゼンテーション層が提供できる変換機能の1つです。

  • セッション層:セッション層は、プレゼンテーション層エンティティ間の通信セッションの確立、管理、および終了を担当します。この層での通信は、異なるデバイス内のアプリケーション間のサービス要求と応答で構成されます。

  • トランスポート層:トランスポート層は、ホストからのエンドツーエンドのリンクを確立します。トランスポート層の役割は、エラー制御やフローの処理など、上位層のプロトコルにエンドツーエンドの信頼性の高い透過的なデータ送信サービスを提供することです。制御の問題。この層は、下位層のデータ通信の詳細を上位層から保護するため、上位層のユーザーには、ユーザーが制御および設定できる2つの送信エンティティ間のホスト間で信頼性の高いデータパスのみが表示されます。 。通常、TCPUDPはこの層にあると言います。ここでは、ポート番号が「終了」です。

  • ネットワーク層:この層は、IPアドレッシングを介して2つのノード間の接続を確立し、送信元エンドのトランスポート層から送信されたパケットに適切なルーティングノードとスイッチングノードを選択し、アドレスに従って宛先エンドのトランスポート層に正しく送信します。 。通常、IP層と呼ばれます。この層は、私たちがよくIPプロトコル層と呼ぶものです。IPプロトコルはインターネットの基盤です。

  • データリンク層:ビットをバイトに結合し、次にバイトをフレームに結合し、リンク層アドレス(イーサネットはMACアドレスを使用)を使用してメディアにアクセスし、エラー検出を実行します。

    データリンク層は、論理リンク制御サブレイヤー(LLC)とメディアアクセス制御サブレイヤー(MAC)の2つのサブレイヤーに分かれています。
    MACサブレイヤーは、CSMA / CDアルゴリズム、データエラーチェック、フレーミングなどを処理します。LLCサブレイヤーは、前のプロトコルがデータリンクレイヤーを共有できるようにいくつかのフィールドを定義します。実際の使用では、LLCサブレイヤーは必要ありません。

    MACアドレスはネットワークカードのROMに固定されており、48ビット、16進数、最初の24ビットは製造元コード、最後の24ビットはシリアル番号です。
    WindowsはローカルMACアドレスipconfig / allをチェックし、物理アドレスはローカルMACアドレスです:F4-8C-50-31-80-99、16進数は4桁の2桁です。

  • 物理層:実際の最終的な信号伝送は、物理層を介して実現されます。ビットストリームは、物理メディアを介して送信されます。レベル、速度、およびケーブルピンが指定されます。一般的に使用されるデバイスは、(さまざまな物理デバイス)ハブ、リピーター、モデム、ネットワークケーブル、ツイストペア、および同軸ケーブルです。これらは、物理層の伝送媒体です。

TCP / IPモデル(現実的)

  • TCP / IP5層プロトコルとOSI7層プロトコル間の対応

ここに画像の説明を挿入

  • 各フロアで異なる機器が稼働しています
  1. 物理層機器、シールド付きツイストペア、シールドなしツイストペア、ハブ、コンバーター、リピーター。コンバーターとモジュレーターの両方がデジタル/アナログ変換に使用されます。リピーターは、送信信号を増幅するために使用されます。ハブは、複数のコンピューターを接続してローカルエリアネットワークを形成することです。ハブはバスタイプのネットワーク構造を使用しているため、ハブに接続されているデバイスがデータを送信する場合、他のすべてのデバイスは待機する必要があります。ハブ内にはオペレーティングシステムがなく、MACアドレスキャッシュもないため、宛先を特定できません。データパケット、したがって、データパケットをブロードキャスト方式で各デバイスに送信し、受信者は、データパケット内のMAC情報に従って、データパケットが失われるのではなく、自分自身に送信されるかどうかを判断します。スイッチの価格が下がると、ハブはもはや一般的ではありません。
  2. データリンク層機器、スイッチ、ブリッジ、ネットワークカード。ネットワークブリッジはもはや一般的ではありません。ネットワークブリッジはポートの少ないスイッチであり、スイッチはポートの多いネットワークブリッジです。スイッチ、エラーチェック、エラーフレームは転送されません。スイッチはポートにデータを送信します。最初にブロードキャストを送信するときは、オペレーティングシステムと学習機能を備えているため、最初にこのポートのMACアドレスをキャッシュし、このデバイスに送信されるときにキャッシュします。繰り返しますが、ブロードキャストは送信されません。
  3. ネットワーク層機器、ルーター。ルーター自体は、物理層、データリンク層、ネットワーク層の3層構造になっています。
  4. ファイアウォールはネットワーク層とトランスポート層で機能し、管理者が設定したネットワークポリシーに従ってネットワークアクセス制御を行います。ハードウェアとソフトウェアのファイアウォールがあり、ハードウェアは高価です。

スイッチはIPを認識せず、スイッチはMACアドレスを介してのみ通信でき、LAN内でのみ通信できます。ネットワークセグメントを通過すると、スイッチを介して通信できなくなります。

ルーターを介してネットワークセグメント間で通信するため。

ゲートウェイ、LAN全体の出口。ローカルエリアネットワークで処理できないデータパケットは、処理のためにゲートウェイに渡されます。外部ネットワークと通信する場合、ソースMacは送信者のMacであり、ターゲットMacはローカルエリアネットワークのゲートウェイです。外部ネットワークへのイントラネット通信の場合、内部IPは外部ネットワークにアクセスできないため、データパケットがゲートウェイに送信されると、ゲートウェイは内部IPの外部に自身のパブリックIPをラップします。これはNATネットワークアドレスと呼ばれます。翻訳。パブリックネットワーク通信の外部ネットワークの場合、NATネットワークアドレス変換は行われません。複数のルートの後、IPは変更されなくなります。

ネットワークでデータを送信する場合、ソースMacは常に変化しており、ルーティングのレイヤーを通過する限り変化します。

ここに画像の説明を挿入

  • 各層に実装されているプロトコルも異なります。つまり、各層のサービスも異なります。

ドメインネーム解決システムDNSはUDPとTCPの両方を使用します。DNSサーバーにはマスターサーバーとスレーブサーバーがあり、それらの間でデータを同期するときにTCPが使用されます。ブラウザーにドメイン名を入力するときは、IPアドレスに解決する必要があり、このときUDPが使用されます。

LANでは、ユーザーAはIPを介してユーザーBに接続されていますが、スイッチはIPを認識しませんが、ローカルエリアネットワーク内のすべてのコンピューターのmacとipに対応するテーブルがあります。arpプロトコルは、ローカルエリアネットワークで通信するときに内部ネットワークIPをMACアドレスに変換するプロトコルです。

ローカルエリアネットワークでは、ウィンドウはコマンドラインでarp -aと入力して、ローカルエリアネットワークのmacとipの間の対応を表示します。

データリンク層は非常にあいまいであり、どの層に属しているかを区別することは困難です。

ここに画像の説明を挿入

  • データカプセル化プロセス
モデルレベル データ構造
アプリケーション層 上位レベルのデータ
トランスポート層 tcpヘッダー上位層データ
ネットワーク層 ipヘッダーtcpヘッダー上位層データ
データリンク層 macヘッダーipヘッダーtcpヘッダー上位層データ
  • IPとポート
  1. インターネット上のすべてのホストとルーターには、ネットワーク番号とホスト番号を含むIPアドレスがあります。アドレスはipv4(32ipビット)またはipv6(128ビット)です。ipconfigで表示できます。
    0 号是保留端口
    1-1024 是固定端口(程序员不要使用),又叫有名端口,即被某些程序固定使用,一般程序员不使用.
        22: SSH 远程登录协议 23: telnet 使用
        25: smtp 服务使用
        21: ftp 使用
        80: iis 使用 7: echo 服务
    1025-65535 是动态端口,这些端口,程序员可以使用.

注意を払う

  1. コンピューターで(特にサーバーとして)できるだけ少ないポートを開きます
  2. ポートは1つのプログラムでのみ監視できます
  3. netstat -anを使用すると、このマシンでリッスンしているポートを確認できます
  4. netstat -anbを使用して、リスニングポートのpidを表示し、タスクマネージャーと組み合わせて安全でないポートを閉じることができます。

server.go

    package main
    import (
        "fmt"
        "net" //做网络socket开发时,net包含有我们需要所有的方法和函数
        _"io"
    )

    func process(conn net.Conn) {

        //这里我们循环的接收客户端发送的数据
        defer conn.Close() //关闭conn

        for {
            //创建一个新的切片
            buf := make([]byte, 1024)
            //conn.Read(buf)
            //1. 等待客户端通过conn发送信息
            //2. 如果客户端没有wrtie[发送],那么协程就阻塞在这里
            //fmt.Printf("服务器在等待客户端%s 发送信息\n", conn.RemoteAddr().String())
            n , err := conn.Read(buf) //从conn读取
            if err != nil {
                
                fmt.Printf("客户端退出 err=%v", err)
                return //!!!
            }
            //3. 显示客户端发送的内容到服务器的终端
            fmt.Print(string(buf[:n])) 
        }
    }

    func main() {
        fmt.Println("服务器开始监听....")
        //net.Listen("tcp", "0.0.0.0:8888")
        //1. tcp 表示使用网络协议是tcp
        //2. 0.0.0.0:8888 表示在本地监听 8888端口
        listen, err := net.Listen("tcp", "0.0.0.0:8888")
        if err != nil {
            fmt.Println("listen err=", err)
            return 
        }
        defer listen.Close() //延时关闭listen

        //循环等待客户端来链接我
        for {
            //等待客户端链接
            fmt.Println("等待客户端来链接....")
            conn, err := listen.Accept()
            if err != nil {
                fmt.Println("Accept() err=", err)
                
            } else {
                fmt.Printf("Accept() suc con=%v 客户端ip=%v\n", conn, conn.RemoteAddr().String())
            }
            //这里准备其一个协程,为客户端服务
            go process(conn)
        }
    }

client.go

    package main
    import (
        "fmt"
        "net"
        "bufio"
        "os"
        "strings"
    )

    func main() {
        conn, err := net.Dial("tcp", "192.168.20.253:8888")
        if err != nil {
            fmt.Println("client dial err=", err)
            return 
        }
        //功能一:客户端可以发送单行数据,然后就退出
        reader := bufio.NewReader(os.Stdin) //os.Stdin 代表标准输入[终端]

        for {
            //从终端读取一行用户输入,并准备发送给服务器
            line, err := reader.ReadString('\n')
            if err != nil {
                fmt.Println("readString err=", err)
            }
            //如果用户输入的是 exit就退出
            line = strings.Trim(line, " \r\n")
            if line == "exit" {
                fmt.Println("客户端退出..")
                break
            }

            //再将line 发送给 服务器
            _, err = conn.Write([]byte(line + "\n"))
            if err != nil {
                fmt.Println("conn.Write err=", err)	
            }
        }
    }

おすすめ

転載: blog.csdn.net/weixin_54707168/article/details/114005941