1. ホーム
  2. Web プログラミング
  3. その他全般

TCPとUDPのプロトコルの原理と違いについての深い理解

2022-01-03 05:03:46

ネットワークプログラミングには、IPアドレス、ポート番号、通信プロトコルの3つの要素がありますが、次に、TCPとUDPという2つの通信プロトコルに焦点を当て、プログラミングの実装について説明します。

まず、IPアドレス、ポート番号、通信プロトコルについて知っておく必要があります。

I. IPアドレス

ネットワーク上のコンピュータは、IPアドレスによって一意に識別され、IPv4とIPv6がある。IPv4では10進数か2進数で表現し、10進数は以下のような表現が一般的です。 192.168.1.131 IPv6では16進数で表現するが、これはあまり使われていない。

IPアドレス関連の情報を見る方法。

Windowsでcmdを起動し、コマンドを入力します。 ipconfig と入力し、Enterキーを押すと表示されます。LinuxまたはMacシステムでは、ターミナルを開いて ifconfig コマンドを実行し、Enterキーを押すと表示されます。

ii. ポート番号

ポート番号とは、コンピュータ内のアプリケーションを表す整数のラベルで、異なるアプリケーションを区別するために使用されます。

0 ~ 1024 は、システムで使用または予約されているポート番号です。 0 ~ 65535 は有効なポート番号です。つまり、あるプログラムのポート番号を定義したいときに 1024 ~ 65535 を整数の範囲で指定します。

例えば、以前習ったMySQLのポート番号は3306、SQLServerのポート番号は1433、確認したOracleのポート番号は1521です。

これらのデータベースに対応するポート番号は、後でデータベースに接続するときに使うように、必ず頭の奥底に隠しておいてください。

III. 通信プロトコル

わかりやすく言うと、通信プロトコルはネットワーク通信におけるルールで、2種類に分けられます。TCPプロトコルとUDPプロトコルの2種類があります。

まず1つ目。TCPプロトコル
英語名:Transmission Control Protocol
中国語名:Transmission Control Protocol
プロトコルの説明。TCPは、コネクション指向で信頼性の高い、バイトストリームベースのトランスポート層通信プロトコルである。

例 電話をかけるには、お互いが接続されていないと会話が成立しない

特徴:低効率、より安全なデータ転送

2位:UDPプロトコル
英語名:User Datagram Protocol
中国語名:Datagram Protocol
プロトコルの説明。UDPはコネクションレス型のトランスポート層通信プロトコルです。

例 データグラムのサイズを64kに制限して、両者間を接続せずにテキストメッセージを送信する。

特徴:高効率、安全でないデータ伝送、パケットロスが発生しやすい

IV. 三要素関係図とネットワークモデル図

1、ネットワーク・プログラミング3要素関係図

注:写真のポート番号とIPアドレスはデモ用であり、本物ではありません

2. OSI参照モデル、TCP/IP参照モデル

V. TCPプログラミング

TCPはバイトストリームをベースにしたトランスポート層通信プロトコルなので、TCPのプログラミングはIOストリームプログラミングが基本になります。

クライアントには Socket クラスでオブジェクトを作成します。サーバー側では ServerSocket を呼び出してオブジェクトを作成し、そのオブジェクトが accept() メソッドでクライアントからのアクセスを待ち受けます。

クライアントサイドとサーバーサイドの図。

クライアントサイドとサーバーサイドの実装手順。

前提条件 クライアントサイド関連のコードとサーバーサイド関連のコードの2つのモジュールからなるプロジェクトを作成します。

ディレクトリ構成は以下の通りです。

クライアント

1. 作成 Socket オブジェクトを作成し、サーバー側アプリケーションのポート番号とサーバー側ホストの IP アドレスを指定します。

2. 2. Socket オブジェクトを呼び出して getOutputStream() メソッドを使用して、バイト出力ストリームオブジェクトを取得します。

3. バイト出力ストリームの write(byte[] buf) または write(int b) 指定されたデータをサーバーに送信します。

4. ストリームを閉じるのを忘れないように。

サーバー側

1. 作成 ServerSocket オブジェクトを作成し、アプリケーションのポート番号を指定します。ポート番号は、クライアントが指定したポート番号と同じである必要があります。

2. を使用します。 ServerSocket オブジェクトの accept() メソッドは、クライアントから送られたリクエストを聞き、そのリクエストに応じた Socket オブジェクトを作成します。

3. を呼び出す。 Socket オブジェクトの getInputStream() メソッドは、バイト入力ストリームオブジェクトを取得します

4. バイト入力ストリームオブジェクトの read(byte[] buf) または read() メソッドを使用してデータを取得します。

5. ストリームを閉じることを忘れないでください。

インスタンスです。

クライアントからサーバーサイドにメッセージを送信し、サーバーサイドに表示する。

クライアントクラス(クライアント側)

package cn.tkrnet.client;

import java.io.IOException;
import java.io.OutputStream;
import java.net;

public class Client {
    public static void main(String[] args) throws IOException {
        
        //create the Socket object, specify the IP address to be sent to the server side, and the port number to be received by the server-side application
        //localhost represents the local IP address
        Socket client = new Socket("localhost",9000);
        
        //get the output stream for sending data to the server side
        OutputStream os = client.getOutputStream();
        
        os.write("Java is my friend ! ".getBytes());
        System.out.println("Message sent");

        //close the stream
        os.close();
        client.close();
    }
}


サーバークラス(サーバーサイド)

package cn.tkrnet.server;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net;

public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("---ServerSocket is open--");

        // Create ServerSocket object, here the port number must be the same as the client's port number
        ServerSocket server = new ServerSocket(9000);

        // call the method accept(), used to listen to the request sent by the client
        Socket socket = server.accept();

        //Get the input stream object
        InputStream is = socket.getInputStream();

        //read the data in the input stream
        int b = 0;
        while ((b =is.read()) ! = -1){
            System.out.print((char)b);
        }
        //close the stream
        is.close();
        socket.close();
        server.close();
    }
}


ヒント:プログラムを実行するときは、必ずサーバー側のプログラムコードを先に実行し、次にクライアント側のプログラムコードを実行するようにしてください。これは、サーバー側がオンになっていることを前提に、クライアントがサーバーにリクエストを送る必要があるためです。

サーバークラス(サーバー側)の実行結果です。

-サーバーサイドがオンになっている --。

Clientクラス(クライアント側)を実行すると、以下のような結果が得られます。

メッセージは送信されました

Clientクラス(クライアント側)が実行された後、Serverクラス(サーバー側)がメッセージを受信し、以下のような結果で実行されます。

--サーバーサイドはオープンです --Java is my friend !

分析例です。

サーバーサイドの起動後、サーバーサイドの accept() メソッドは、クライアントがサーバーに接続するまで待機し、サーバー側はクライアントからのデータをストリームから読み取ります。 このとき

失礼ながら、これは一方通行のコミュニケーションの超超超単純な例です。

VI. UDPプログラミング

UDPはデータグラムを使用してデータを伝送する。クライアント側とサーバー側はなく、送信者と受信者のみで、どちらも先に起動してもエラーは報告されませんが、パケットロスは発生します。送信できる内容には単語制限があり、サイズは64kまでと決められています。

送信機と受信機の実装のステップ。

前提条件 送信側関連コードと受信側関連コードの2つのモジュールからなるプロジェクトを作成します。

ディレクトリ構成は以下の通りです。

送信者

1. 作成 DatagramSocket オブジェクトを作成し、アプリケーションのポート番号を指定するかしないかを選択します。

2. 送信するデータを準備する

3、作成 DatagramPacket このオブジェクトは、送信データをパッケージ化するために使用され、送信内容、送信量、送信先、受信者のポート番号の4つのパラメータを指定する必要があります。

4. 呼び出し DatagramSocket オブジェクトの send() メソッドはデータを送信します。

5. ストリームを閉じることを忘れないでください。

レシーバーです。

1. 作成 DatagramSocket オブジェクトを作成し、受信機のポート番号を指定する。

2. を作成します。 byte 型の配列を作成し、送信者からのデータを受信します。

3. 作成 DatagramPacket オブジェクトを作成し、データを受信できるようにします。

4. を呼び出す。 DatagramSocket オブジェクトの receive() メソッドを使用してデータを受信します。 は、その

5. を使用します。 String クラスのコンストラクタで byte 型の配列に変換します。 String 型に変換して表示します。

6. ストリームを閉じることを忘れないでください。

インスタンスです。

送信者がメッセージを送信し、受信者がそれを受信し、表示する。

センダークラス(送信者)

package cn.tkrnet.Sender;

import java.io.IOException;
import java.net.*;

public class Sender {
    public static void main(String[] args) throws IOException {

        // Create a receiving or sending datagram socket and specify the sender's port number as 7770
        DatagramSocket ds = new DatagramSocket(7770); //Port number can also be unspecified
        System.out.println("----sender--");

        //create datagram object to send data
        byte[] b = "Java is my friend! ".getBytes();

        //8800 is the port number of the receiver, netAddress.getByName("localhost") is to get the IP address of the host
        DatagramPacket dp = new DatagramPacket(b,b.length, InetAddress.getByName("localhost"),7788);

        ds.send(dp); //send datagram
        System.out.println("data has been sent");
        //close the stream
        ds.close();
    }
}


Receiverクラス(レシーバー)

package cn.tkrnet.receiver;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receiver {
    public static void main(String[] args) throws IOException {
        System.out.println("----receiver--");

        // Create a datagram socket object, specifying the port number to be the same as the port number on which the sender sends data
        // (not the sender's port number 7770, but the sender's port number for sending data 7788)
        DatagramSocket ds = new DatagramSocket(7788);

        // Create the object to receive the datagram
        byte[] b = new byte[1024];
        DatagramPacket dp = new DatagramPacket(b,b.length);

        // Receive data
        ds.receive(dp);
        System.out.println(new String(b,0,dp.getLength()));
        //Close the stream
        ds.close();
    }
}


補足:プログラムを実行する際、送信側のプログラムを先に実行しても、受信側のプログラムを先に実行してもエラーにはなりませんが、パケットロスの可能性があるので、通常は受信側のプログラムコードを先に実行し、その後、送信側のプログラムコードを実行します。

レシーバクラス(受信機)の結果です。

--- レシーバー ---

Senderクラス(送信者)は以下のような結果で実行されます。

--- 送信者 --- 送信されたデータ

Senderクラス(送信者)が実行された後、Receiverクラス(受信者)がメッセージを受信し、次のような結果で実行されます。

--- 受信機 --- Javaは私の友達です!

解析例です。

ポート番号7788のプログラムは、受信側が先に動作を開始した場合にのみ存在し、送信側はデータを