高度なJava-ネットワークプログラミングの使用

1.ネットワークプログラミングの概要

ネットワークプログラミングとは、インターネット上の2つ(またはそれ以上)のデバイス(コンピューターなど)間のデータ転送を可能にするプログラムを記述することです
1.目的:通信するネットワークプロトコルを介して他のコンピューターと直接または間接的にデータを通信します。

2.ネットワークプログラミングで注意すべき2つの問題

①ネットワーク上で1つ以上のホストを正確に見つけた場合は、ホスト上の特定のアプリケーションを見つけます

②ホスト発見後、確実かつ効率的にデータを転送する方法

2.ネットワーク通信における2つの重要な要素

要素1、IPおよびポート番号:

①IP:インターネット上のコンピューターを一意に識別します(抽象化しすぎて覚えにくい)②ポート
番号:ホスト上の特定のアプリケーション(プロセス)を見つけます
③IP分類:IPv4とIPv6、World Wide Webとローカルエリアネットワークの
違い④JavaでInetAddressクラスはIPを表します
。⑤ドメイン名:www.baidu.com DNS(ドメイン名解決サーバー)。これは、IPへのアクセスに使用できます。⑥
ローカルループアドレス:127.0.0.1対応:localhost

ポート番号:

①プロセスごとにポート番号が異なる

②は16ビット整数0-65535として指定されています


ポート分類認識ポート:0〜1023が定義済みサービス通信で占有(例:HTTPでポート80が占有)

登録ポート:ユーザープロセスまたはアプリケーションに割り当てられた1024〜49151(例:Tomcatはポート8080を使用し、MySQLはポート3306を使用)

動的/プライベートポート:49152〜65535

④ポート番号とIPアドレスの組み合わせにより、ネットワークソケットが生成されます。

要素2.ネットワーク通信プロトコル:(TCP / IP参照モデル)

ここに画像の説明を挿入
概念:
コンピュータネットワークで通信を実現するには、いくつかの制約が必要です。つまり、レート、伝送コード、コード構造、伝送制御ステップ、エラー制御などの標準を設定する通信プロトコルです。

通信プロトコルの階層化:物理リンク層、IP層、トランスポート層、アプリケーション層

トランスポート層プロトコルには2つの重要なプロトコルがあります。

①伝送制御プロトコル(TCP)

②ユーザーデータグラムプロトコル(UDP)

TCP / IPプロトコル:これは、伝送制御プロトコル(TCP)およびネットワーク相互接続プロトコル(IP)にちなんで名付けられたプロトコルのグループであり、さまざまな機能を持ち、互いに関連する複数のプロトコルを含みます。

TCPとUDPの違い

TCPプロトコル:(ライフケース:呼び出し)

1. TCPプロトコルを使用する前に、TCP接続を確立して送信データチャネルを形成する必要があります
。2.送信前に、ポイントツーポイント通信に「スリーウェイハンドシェイク」方式を使用します。これは信頼性があります。3. TCP
通信の2つのアプリケーションプロセス:クライアント、サーバー
4.接続中に大量のデータを送信できます
5.送信が完了した後、確立された接続を解放する必要があるため、非効率的です

3つのハンドシェイク:

ここに画像の説明を挿入
最初のステップ:クライアントは、synをサーバーに送信してハンドシェイクを開始します。

ステップ2:サーバーは、syn + ackを受け取った後、クライアントに応答します。

3番目のステップ:クライアントがsyn + ackを受信した後、サーバーのsyn + ackを受信したことを示すackでサーバーに応答します。

ブラウザとリモートWebサーバーは、TCPスリーウェイハンドシェイクネゴシエーションを介してTCP / IP接続を確立します。ハンドシェイクには、同期メッセージ、同期応答メッセージ、および応答メッセージが含まれており、これら3つのメッセージは、ブラウザとサーバーの間で転送されます。ハンドシェイクは最初にクライアントによる通信の確立を試み、次にサーバーがクライアントの要求に応答して受け入れ、最後にクライアントが要求が受け入れられたというメッセージを送信します。

3ウェイハンドシェイクの理由:無効なメッセージがサーバーに送信されるのを防ぐため。
4回振ります

ここに画像の説明を挿入

ハンドの最初の波:データ送信が終了した後、クライアントアプリケーションプロセスは接続解放セグメントを送信し、データの送信を停止しますそのヘッダー:FIN = 1、seq = x。

2番目の波:接続解放メッセージセグメントを受信した後、サーバーは確認メッセージを送信します。そのヘッダーは次のとおりです:ack = x + 1、seq = z。この時点で、接続はセミクローズ状態になり、クライアントはサーバーにデータを送信しなくなりました。サーバーは送信を続けます。

3番目の波:サーバーにクライアントに送信するデータがない場合、そのアプリケーションプロセスはサーバーにTCP接続を解放するよう通知します。

4番目の波:クライアントが接続解放セグメントを受信した後、2MSL(メッセージの最大寿命)の後で、このTCP接続は実際に終了し、通信パーティは別れを完了しました。

UDPプロトコル:(ライフケース:SMSを送信)

1.接続を確立せずに、データ、送信元、および宛先をデータパケットにカプセル化する

2.各データグラムのサイズは64kに制限されています

3.相手が使用可能かどうかに関係なく、受信者は受信を確認しないため、信頼できません。

4.放送できます

5.データ送信の最後にリソースを解放する必要がなく、オーバーヘッドが小さく、速度が速い

ネットワーク内のホスト間の通信を実現する方法

1.通信の両当事者のアドレス(IPおよびポート番号)
2.特定の規則(ネットワーク通信プロトコル)

InetAddressの2つのメソッドをインスタンス化する方法:getByName()、getLocalHost

2つの一般的な方法:
GETHOSTNAME()
はgetHostAddress()

public class InetAddressTest {

    public static void main(String[] args) {

        try {
            //实例化
            //getAllByName()
            InetAddress inet = InetAddress.getByName("192.168.10.100");//  --->/192.168.10.100
            System.out.println(inet);

            InetAddress inet1 = InetAddress.getByName("www.baidu.com");//www.baidu.com/39.156.66.14
            System.out.println(inet1);

            InetAddress inet2 = InetAddress.getByName("127.0.0.1");//   /127.0.0.1
            System.out.println(inet2);

            //获取本机的IP地址
            InetAddress localHost = InetAddress.getLocalHost();
            System.out.println(localHost);//


            //getHostName()

            //getHostAddress()



        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

    }

}

第三に、TCPネットワークプログラミングの実現

1.クライアントがサーバーに情報を送信し、サーバーがデータをコンソールに表示します。

注:最初にサーバーを起動し、次にクライアントを起動します
public class TCPTest {
    /*
    客户端
     */
    @Test
    public void client(){
        Socket socket = null;
        OutputStream ops = null;
        try {
            //1.实例化对象,指明ip和端口号
            InetAddress inet = InetAddress.getByName("127.0.0.1");
            socket = new Socket(inet,8899);

            //2.获取输出字节流,用于输出数据
            ops = socket.getOutputStream();
            //3.写出数据
            ops.write("你好,我是客户端".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源关闭
            if (ops!=null){
                try {
                    ops.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /*
    服务端:接收客户端的数据
     */
    @Test
    public void server() {
        ServerSocket ss = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            //指明端口号和
            //1.实例化服务器端的ServerSocket对象,指明自己的端口号
            ss = new ServerSocket(8899);

            //2.调用accept(),接收来自客户端的socket
            socket = ss.accept();
            //3.获取输入流
            is = socket.getInputStream();

            //过程,不建议,可能会乱码
//        byte[] bytes =new byte[1024];
//        int len;
//        while ((len = is.read(bytes)) != -1){
//            String string =new String(bytes,0,len);
//            System.out.println(string);
//        }
            //4.读取输入流中的数据
            baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[5];
            int len;
            while ((len = is.read(bytes)) != -1){
                baos.write(bytes,0,len);
            }
            System.out.println(baos.toString());
            //收到来自谁的数据,获取客户端的Ip地址
            System.out.println("收到了来自:"+socket.getInetAddress().getHostAddress()+"的信息");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5.关闭资源
            if (baos!=null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

効果のデモ:
ここに画像の説明を挿入

2.クライアントはファイルをサーバーに送信し、サーバーはファイルをローカルに保存します。

IOExceptionをスローする代わりに、try-catch-finallyを使用する必要があります

public class TCPTest1 {

    /*
    客户端
     */
    @Test
    public void client() throws IOException {
        //1.创建socket对象,指定ip和端口号
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
        //2.获取输出流
        OutputStream os = socket.getOutputStream();
        //3.获取输入流
        FileInputStream fis = new FileInputStream(new File("IO流的分类.png"));
        //4.具体的读写过程
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read(bytes)) != -1){
            os.write(bytes,0,len);
        }
        //5.关闭资源
        fis.close();
        os.close();
        socket.close();

    }

    /*
    服务端
     */
    @Test
    public void server() throws IOException {
        //1.创建ServerSocket对象,指定自己的端口号
        ServerSocket ss = new ServerSocket(9090);
        //2.使用accept(),获取客户端的socket
        Socket socket = ss.accept();
        //3.获取客户端的输入流
        InputStream is = socket.getInputStream();
        //4.指明输出的位置
        FileOutputStream fos = new FileOutputStream(new File("IO流的分类2.png"));
        //5.具体的操作过程
        byte[] bytes = new byte[1024];
        int len;
        while ((len = is.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        System.out.println("接收成功");
        //6.资源关闭
        fos.close();
        is.close();
        socket.close();
        ss.close();

    }
}

3.ファイルをクライアントからサーバーに送信します。サーバーはそれをローカルに保存し、「正常に送信されました」をクライアントに返します。
public class TCPTest2 {
    /*
   客户端
    */
    @Test
    public void client() throws IOException {
        //1.创建socket对象,指定ip和端口号
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
        //2.获取输出流
        OutputStream os = socket.getOutputStream();
        //3.获取输入流
        FileInputStream fis = new FileInputStream(new File("IO流的分类.png"));
        //4.具体的读写过程
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read(bytes)) != -1){
            os.write(bytes,0,len);
        }

        //关闭数据的输出,服务器就会得到明确的指示,如果没有shutdownOutput(),就会被read()阻塞,执行不了下面的操作
        socket.shutdownOutput();

        //5.接收来自于服务端的数据,并显示到控制台上
        InputStream is = socket.getInputStream();

        //为了不乱码,使用ByteArrayOutputStream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] bytes1 = new byte[5];
        int len1;
        while ((len1 = is.read(bytes1)) != -1){
             baos.write(bytes1,0,len1);
        }
        //显示数据
        System.out.println(baos.toString());

        //6.关闭资源
        fis.close();
        os.close();
        socket.close();
        baos.close();

    }

    /*
    服务端
     */
    @Test
    public void server() throws IOException {
        //1.创建ServerSocket对象,指定自己的端口号
        ServerSocket ss = new ServerSocket(9090);
        //2.使用accept(),获取客户端的socket
        Socket socket = ss.accept();
        //3.获取客户端的输入流
        InputStream is = socket.getInputStream();
        //4.指明输出的位置
        FileOutputStream fos = new FileOutputStream(new File("IO流的分类4.png"));
        //5.具体的操作过程
        byte[] bytes = new byte[1024];
        int len;
        //read()为阻塞式方法,一直停留在循环中
        while ((len = is.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        //6.服务端给客户端反馈
        System.out.println("发送成功!");

        OutputStream os = socket.getOutputStream();
        os.write("数据发送成功".getBytes());

        //7.资源关闭
        fos.close();
        is.close();
        socket.close();
        ss.close();
        os.close();

    }
}

4、UDPプロトコルネットワークプログラミング


    /*
    发送端
     */
    @Test
    public void sender() throws IOException {
        //1.实例化DatagramSocket
        DatagramSocket socket = new DatagramSocket();

        //2.数据的声明
        String str = "UDP的网络编程";
        //3.转换为字节数组
        byte[] data = str.getBytes();

        //4.指定ip
        InetAddress inet = InetAddress.getLocalHost();

        //5.实例化DatagramPacket(数据报)
        DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,9090);

        //6.发送数据报
        socket.send(packet);

        //7.关闭资源
        socket.close();

    }
    /*
    接收端
     */
    @Test
    public void  receiver() throws IOException {
        //1.实例化DatagramSocket,指定自己的端口号,确定自己的进程
        DatagramSocket socket = new DatagramSocket(9090);

        //2.数据封装在DatagramPacket,不再发送,不用指定端口号和ip
        byte[] bytes = new byte[100];
        DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);

        //3.接收数据
        socket.receive(packet);
        //4.输出数据
        //packet.getData()获取packet中的数据,从0开始,到哪里结束
        System.out.println(new String(packet.getData(),0,packet.getLength()));

        //5.资源关闭
        socket.close();
    }

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

1. URL(Uniform Resource Locator):インターネット上のリソースのアドレスを表すUniform Resource Locator

2. URLの基本構造は5つの部分で構成されています。

<転送プロトコル>:// <ホスト名>:<ポート番号> / <ファイル名>#クリップ名?パラメータリスト
例:http://192.168.1.100:8080/helloworld/index.jsp?ユーザー名=管理者&パスワード= 123456

3.共通メソッド:
public String getProtocol():URLのプロトコル名を取得します

public String getHost():URLのホスト名を取得します

public String getPort():URLのポート番号を取得します

public String getPath():URLのファイルパスを取得します

public String getFile():URLのファイル名を取得します

public String getQuery():URLのクエリ名を取得します

public class URLTest {
    public static void main(String[] args) {
        try {
            URL url = new URL("http://192.168.1.100:8080/helloworld/index.jsp?username=admin&password=123456");

            System.out.println(url.getProtocol());
            System.out.println(url.getHost());
            System.out.println(url.getPort());
            System.out.println(url.getPath());
            System.out.println(url.getFile());
            System.out.println(url.getQuery());



        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

URLネットワークプログラミングを使用してTomcatにファイルをダウンロードする
public class URLTest1 {
    public static void main(String[] args) {
        HttpURLConnection urlConnection = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            //下载Tomcat服务器中的数据,需要开启Tomcat服务器
            URL url =new URL("http://192.168.1.100:8080/helloworld/IO流的分类.png");

            //找到连接对象
            urlConnection = (HttpURLConnection) url.openConnection();

            //获取连接,访问服务器
            urlConnection.connect();

            //得到一个输入流
            is = urlConnection.getInputStream();

            //将从服务器得到的数据,写入到具体的文件中,再main方法中,会写入到当前工程下
            fos = new FileOutputStream("IO流的分类5.png");

            //读写过程
            byte[] bytes = new byte[1024];
            int len;
            //读取文件
            while ((len = is.read(bytes)) != -1){
                //写入到文件中
                fos.write(bytes,0,len);
            }
            System.out.println("下载完成!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (urlConnection != null){
                //断开连接
                urlConnection.disconnect();
            }
        }
    }
}

元の記事を19件公開しました 賞賛されました0 訪問数475

おすすめ

転載: blog.csdn.net/weixin_43244120/article/details/105621397