Javaのネットワーク


IPアドレスとポート


パソコンには自分の住所があります.これがIP(インターネットプロトコル)です.
各ネットワークアダプタ(LANカード)に割り当てられ、1台のコンピュータに2つのネットワークカードがあり、2つのIPアドレスを割り当てることができます.
接続する相手のIPアドレスがわからなければ、電話番号が分からないのと同じで、プログラムはDNS(ドメイン名システム)を使って接続するコンピュータのIPアドレスを探します.
ほとんどのサービスを提供するサーバにはドメイン名があります.
ex) www.naver.comのドメイン名でIPアドレス222.12.195.5を登録します.
IPアドレスに比べて、ユーザーはドメイン名を覚えやすく、私たちがよく見ている広告宣伝ドメイン名だけでIPアドレスを宣伝しません.
Webブラウザは、ユーザが入力したドメイン名をDNSに検索してIPを取得し、IPを有するサーバに接続する.
1台のコンピュータ上で1つのIPが同時にWebサーバ、DBMS、FTPサーバなどを実行することができる.異機種クライアントは、どのサーバと通信するかを決定する必要があります.
IPはコンピュータのネットワークアダプタにしか到達できない情報であるため、ポート番号であるコンピュータ上で実行されるサーバを選択するために追加の情報が必要である.
サーバは、ポートバインドと呼ばれる固定ポート番号を使用して起動します.
ex)Webサーバは基本的に80番にバインドされ,FTPサーバは21番にバインドされる.
クライアントがWebサーバに接続するには80回の接続要求が必要であり,FTPサーバに接続するには21回の接続要求が必要である.
クライアントの場合、サーバは送信された情報を受信するためにポート番号を必要とします.これは、固定されたポート番号ではなく、オペレーティングシステム(サーバなど)によって自動的に提供される動的ポート番号です.

TCPネットワーク


転送制御プロトコル(TCP)は、接続向けのプロトコルである.
接続状態でデータ交換を行うプロトコル.
TCPはデータを正確かつ確実に伝達することができる.
欠点は、接続が必要(最も時間がかかる)ことであり、通信回線が最も短くない場合、UDPに比べて遅くなる可能性がある.
Javaは、TCPネットワークに対してSocketクラス(接続されたクライアントとの通信を担当するクラス)とServerSocketクラス(クライアント接続要求を待つときに接続を受け入れるクラス)を提供します.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerExample {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		ServerSocket serverSocket = null;
		
		try {
			serverSocket = new ServerSocket();
			serverSocket.bind(new InetSocketAddress("localhost", 5001)); // 5001번 포트를 바인딩한다. 
		
			while(true) {
				System.out.println("연결기다림");
				Socket socket = serverSocket.accept(); // 클라이언트의 연결 수락 
				InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
				System.out.println("[연결 수락함]" + isa.getHostName());
				
				
			}
			
		}catch(Exception e) {}
		
		if(!serverSocket.isClosed()) {  /// ServerSocket이 닫혀짔지않으면
			
			try {
				serverSocket.close(); // ServerSocket 을 닫자 (언바인딩 => 다른 프로그램에서 패당포트를 재사용할수있다.)
			}catch(IOException e1) {}
		}
		
	}
}
InetSocketAddressオブジェクトには、IPとポート情報を返す方法があります.
String getHostName():クライアントIPが返される
int getPort():クライアントポート番号を返す
String to String():IP:ポート番号で文字列を返す

SOcketの作成と接続を要求


java.net.Socketを使用して、クライアントにサーバへの接続を要求できます.
 try{
 Socket socket = new Socket("localhost", 5001); // 첫번째방법
 Socket socket = new Socket(new InetSocketAddress("localhost", 5001); // 두번째방법
 
 }catch( UnKnownHostException e) {
		//IP표기 잘못된경우 
}catch(IOException e) {
	//해당포트의 서버에 연결할수없는경우 
}
ローカルpc上の5001ポートへの接続を要求するコード
=>接続を要求するには、サーバのIPアドレスとバインドポート番号を指定するだけです.

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerExample {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		ServerSocket serverSocket = null;
		
		try {
			serverSocket = new ServerSocket();
			serverSocket.bind(new InetSocketAddress("localhost", 5001)); // 5001번 포트를 바인딩한다. 
		
			while(true) {
				System.out.println("연결기다림");
				Socket socket = serverSocket.accept(); // 클라이언트의 연결 수락 
				InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
				System.out.println("[연결 수락함]" + isa.getHostName());
				
				
			}
			
		}catch(Exception e) {}
		
		if(!serverSocket.isClosed()) {  /// ServerSocket이 닫혀짔지않으면
			
			try {
				serverSocket.close(); // ServerSocket 을 닫자 (언바인딩 => 다른 프로그램에서 패당포트를 재사용할수있다.)
			}catch(IOException e1) {}
		}
		
		

	}

}
accept()メソッドを繰り返し呼び出すことで複数のクライアント接続のコードを受け入れる
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class ClientExample {

	public static void main(String[] args) {
		
		Socket socket = null;
		
		try {
			socket = new Socket(); // 소켓 생성
			System.out.println("연결 요청");
			socket.connect(new InetSocketAddress("localhost", 5001)); // 연결 요청 
			System.out.println("연결 수락");
			
			
		}catch(Exception e) {
			
		}
		
		if(!socket.isClosed()) {  // 연결되어있지않다면
			
			try {
				socket.close();
			}
			
		catch(IOException e1) {}

			
		}

	}

}
localhost 5001ポートへの接続を要求するコードconnect()メソッドが正常に戻った場合、接続は成功します.

クライアントが接続を要求し、サーバが接続を受け入れる場合、入力ストリームと出力ストリームは、2つのsocketオブジェクトからそれぞれ取得できます.
また,このように交換する過程がTCP 3ウェイ握手である.

スレッド並列処理


サーバの遅延を要求するためにサーバSocketのaccept()を実行したり、socketジェネレータまたはconnetct()を実行したりすると、操作が完了する前にブロックされます.
要するに、Server SocketとSocketは同期(ブロック)方式で駆動されます.
サーバーを実行するメインスレッドが直接I/Oを担当している場合は、I/Oが完了するまで他の操作はできません.
したがって、accept()、connect()、read()およびwrite()は、個別の作業スレッドを作成することによって並列に処理することが望ましい.

図に示すように、上の図に示すように、数千のクライアントがスレッドを同時に使用して並列処理を行うと、サーバのパフォーマンスが急激に低下し、低下します.
スレッドプールを使用する必要があります.

1-2:クライアントが接続を要求する場合は、サーバのスレッドプールで接続を受け入れ、socketを生成します.
3~5個のクライアントがタスク処理要求を発行すると、サーバのスレッドプールは要求を処理し、応答をクライアントに送信します.
スレッドプールで使用されるスレッド数が限られているため、サーバのパフォーマンスが低下します.