LoginSignup
6
7

More than 5 years have passed since last update.

JAVAでTCP/IP+BIOについて実装してみた

Posted at

この記事ではWIN10にインストールしたJava 10.0.1を使っています。

はじめに

システム間の通信を行うには、TCPとUDPというOSIのレイヤ4(トランスポート)のプロトコルがよく使われます。
TCPとUDPのメリットは以下となります:
TCP
- 信頼性が高い
UDP
- スピードが早い
また、TCPとUDPはシステム間の通信をできますが、それ以外、通信するデータに対して何かI/O処理を行わないといけませんので、I/O処理の方式も必要です。ここはブロッキングと(BIO)かノンブロッキング(NIO)がよく使われいます。
今回はTCP/IP+BIOでシステム間の通信を実装してみます。

実装

TCP通信を行うには、ソケットというライブラリを利用します。
Java言語からSocketServerSocketを提供していので、今回はこれらを使ってTCP/IP+BIOを実装してみます。
(公式APIはここ:SocketServerSocket)
サーバ側のファイル(実はローカル)

ソケットを生成し、クライアント側のアクセスを待ち受けます
TcpServerファイル内容:


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

public class TcpServer{
    public static void main (String[] argv) throws Exception{
        try (
            // 8001ポート番号を作成する
            ServerSocket server = new ServerSocket(8001);
            FileOutputStream fos = new FileOutputStream("server_recv.txt");
            FileInputStream fis = new FileInputStream("server_send.txt");
        ){
            System.out.println("wait access...");
            // クライアント側のアクセスを待つ
            Socket socket = server.accept();
            System.out.println("client access.");

            int ch;
            // クライアント側から渡されたストリームをserver_recv.txtに書く
            InputStream input = socket.getInputStream();
            while ((ch = input.read()) != 0) {
                fos.write(ch);
            }
            // server_send.txtに書いた内容ストリームでをクライアント側に渡す
            OutputStream output = socket.getOutputStream();
            while ((ch = fis.read()) != -1) {
                output.write(ch);
            }
            // アクセス終了
            socket.close();
            System.out.println("accsess closed.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

server_send.txt ファイル内容:

server_send

server_recv.txtは空ファイル

クライアント側のファイル

ソケットを生成し、指定されたサーバとポートをアクセスします
TcpClientファイル内容:


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

public class TcpClient{
    public static void main (String[] argv) throws Exception{
        try (
            // 8001ポート番号をアクセス
            Socket socket = new Socket("localhost", 8001);
            FileOutputStream fos = new FileOutputStream("client_recv.txt");
            FileInputStream fis = new FileInputStream("client_send.txt");
        ){

            int ch;
            // client_send.txtに書いた内容ストリームでをサーバ側に渡す
            OutputStream output = socket.getOutputStream();
            while ((ch = fis.read()) != -1) {
                output.write(ch);
            }
            // サーバ側に「転送終了!」旨を渡す
            output.write(0);
            // サーバ側から渡されたストリームをclient_recv.txtに書く
            InputStream input = socket.getInputStream();
            while ((ch = input.read()) != -1) {
                fos.write(ch);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

client_send.txt ファイル内容:

client_send

client_recv.txtは空ファイル

実行

TcpClient.javaとTcpServer.javaをそれぞれをjavacでコンパイルし、javaで実行します

  • TcpServer.classを実行します

サーバを起動し、クライアント側の接続を待ち受け中:

PS C:\Users\ma\Documents\work\javaweb\1> java TcpServer
wait access...
  • TcpClient.classを実行します

クライアントを起動し、サーバ側へアクセスします:

PS C:\Users\ma\Documents\work\javaweb\1> java TcpClient

サーバはクライアント側からの接続を処理したら終了します:

PS C:\Users\ma\Documents\work\javaweb\1> java TcpServer
wait access...
client access.
accsess closed.
PS C:\Users\ma\Documents\work\javaweb\1>

結果検証

server_recv.txt ファイル内容:

client_send

クライアント側から渡された内容(client_send.txt)を上書きすることを検証できました

client_recv.txtも同じくサーバ側から渡された内容(server_send.txt)を上書きされました:

server_send

まとめ

今回はJavaのSocket、ServerSocketライブラリを使ってTCP/IP+BIOの転送路を作りました。
サーバとクライアントの間に、データを双方向に送れることも検証しました。

参考

1.前橋和弥.2016.基礎からのWebアプリケーション開発入門.技術評論社.

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7