JAVA/네트워크 입출력

[Java] TCP 네트워킹

숭어싸만코 2023. 6. 2. 12:59

TCP 네트워킹

-TCP는 연결형 프로토콜로 상대방이 연결된 상태에서 데이터를 주고 받는다.

-클라이언트가 연결 요청을 하고 서버가 연결을 수락하면 고정회선을 통해 데이터 전달

-java.net 패키지에서 ServerSocket 과 Socket 클래스 제공

- ServerSocket : 클라이언트의 연결을 수락하는 서버쪽 클래스
- Socket :  클라이언트 연결요청과 양쪽 데이터를 주고 받을때 사용 되는 클래스

[서버] 
- ServerSocket / Scoket 이용

package study0602.Network;

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

public class ServerExample {
	private static ServerSocket serverSocket = null;

	public static void main(String[] args) {
		// P.831

		System.out.println("---------------------------");
		System.out.println("서버를 종료하면 q 또는 Q를 입력하고 Enter 키를 입력하세요.");
		System.out.println("---------------------------");

		// TCP 서버시작
		startServer();

		// 키보드 입력
		Scanner sc = new Scanner(System.in);
		while (true) {
			String key = sc.nextLine();
			if (key.toLowerCase().equals("q")) {
				break;
			}
		}
		sc.close();

		// TCP서버 종료
		stopServer();

	}//

	private static void startServer() {
		// 작업 스레드 정의
		Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					// ServerSocket 생성 및 Port 바인딩
					serverSocket = new ServerSocket(50001);
					System.out.println("[서버] 시작됨");

					while (true) {
						System.out.println("[서버] 연결 요청을 기다림");
						// 연결 수락
						Socket socket = serverSocket.accept();

						// 연결된 클라이언트 정보 얻기
						InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
						System.out.println("[서버]" + isa.getHostName() + "연결 요청을 수락함");

						// 연결 끊기
						socket.close();
						System.out.println("[서버]" + isa.getHostName() + "의 연결을 끊음");
					}

				} catch (IOException e) {
					// TODO: handle exception
					System.out.println("[서버]" + e.getMessage());
				}
			}
		};
		// 스레드 시작
		thread.start();

	}

	private static void stopServer() {

		try {
			// ServerSocket을 닫고 Port 언바인딩
			serverSocket.close();
			System.out.println("[서버] 종료됨");

		} catch (IOException e1) {
			// TODO: handle exception
		}

	}

}//

[클라이언트] 
- Socket 이용

package study0602.Client;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientExample {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		try {
			//Socket 생성과 동시에 localhost의 50001 Port로 연결 요청;
			Socket socket = new Socket("localhost",50001);
			System.out.println("[클라이언트] 연결성공");
			
			//Socket 닫기
			socket.close();
			System.out.println("[클라이언트] 연결 끊기");
			
		}catch (UnknownHostException e) {
			// IP 표기방법이 잘못되었을경우
		} 
		catch (IOException e) {
			// 해당 포트의 서버에 연결할 수 없는 경우
		}
		
		
		
	}//

}//

 

 

 

입출력 스트림으로 데이터 주고받기

- 클라이언트가 연결 요청( connect( ) )을 하고 서버가 연결 수락 ( accept( ) ) 했다면, 양쪽의 Socket객체로부터 각각 입력 스트림 ( InputStream ) 과 출력 스트림 ( OutPutStream ) 을 얻을 수 있다.

- 문자열을 간편하게 주고 받고 싶다면 보조 스트림 DataOutputStream / DataInputStream을 연결해서 사용 하면 된다.

 

DataOutputStream / DataInputStream 을 이용한 예제

[Server]

package study0602.Network;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class EchoServer {
	private static ServerSocket serverSocket = null;
	public static void main(String[] args) {
		// P.838 입출력 스트림으로 데이터 받기

		
		System.out.println("---------------------------");
		System.out.println("서버를 종료하면 q 또는 Q를 입력하고 Enter 키를 입력하세요.");
		System.out.println("---------------------------");
		
		//TCP 서버시작
		startServer();
		
		//키보드 입력
		Scanner sc= new Scanner(System.in);
		while (true) {
			String key = sc.nextLine();
			if(key.toLowerCase().equals("q")) {
				break;
			}
		}
		sc.close();
		
		//TCP서버 종료
		stopServer();
		
		
	}//
	
	private static void startServer() {
		Scanner sc = new Scanner(System.in);
		// 작업 스레드 정의
		Thread thread = new Thread(){
			@Override
			public void run() {
			try {
				//ServerSocket 생성 및 Port 바인딩
				serverSocket = new ServerSocket(50001);
				System.out.println("[서버] 시작됨");
				
				while (true) {
					System.out.println("[서버] 연결 요청을 기다림");
					//연결 수락
					Socket socket = serverSocket.accept();
					
					//연결된 클라이언트 정보 얻기
					InetSocketAddress isa = 
							(InetSocketAddress)socket.getRemoteSocketAddress();
					System.out.println("[서버]"+ isa.getHostName()+"연결 요청을 수락함");
					//-----------------------------------------------------
					//==데이터 받기
					
					DataInputStream dis = new DataInputStream(socket.getInputStream());
					String message = dis.readUTF();
					System.out.println("[서버] 받은 데이터 : " + message);
					
					//데이터 보내기
					DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
					
					
					System.out.println("=====클라이언트에게 보낼 메세지 입력=====");				
					String send =sc.nextLine();
					System.out.println("=======================");
					dos.writeUTF(send);
					dos.flush();
					
					
					
					
					//----------------------------------------------------
					//연결 끊기
					socket.close();
					System.out.println("[서버]"+isa.getHostName()+ "의 연결을 끊음");
				}
				
			} catch (IOException e) {
				// TODO: handle exception
				System.out.println("[서버]"+e.getMessage());
			}
			}
		};
	//스레드 시작
		thread.start();
		
	}

	private static void stopServer() {
		
		try {
			//ServerSocket을 닫고 Port 언바인딩
			serverSocket.close();
			System.out.println("[서버] 종료됨");
			
		} catch (IOException e1) {
			// TODO: handle exception
		}
		
	}

	
	
	

}//

[Client]

package study0602.Client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class EchoClient {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		try {
			//Socket 생성과 동시에 localhost의 50001 Port로 연결 요청;
			Socket socket = new Socket("localhost",50001);
			System.out.println("[클라이언트] 연결성공");
			
			//----------------------------------------
			
			System.out.println("======메세지 입력======");
			String sendMessage = sc.nextLine();
			
			
			DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
			dos.writeUTF(sendMessage);
			dos.flush();
			System.out.println("[클라이언트] 데이터 보냄: "+sendMessage);
			
			//데이터 받기
			DataInputStream dis=new DataInputStream(socket.getInputStream());
			String receiveMessage = dis.readUTF();
			System.out.println("[클라이언트] 데이터 받음: " +receiveMessage  );
			
			//----------------------------------------			
						
			//Socket 닫기
			socket.close();
			System.out.println("[클라이언트] 연결 끊기");
			
		}catch (UnknownHostException e) {
			// IP 표기방법이 잘못되었을경우
		} 
		catch (IOException e) {
			// 해당 포트의 서버에 연결할 수 없는 경우
		}
		
	}//

}//