* 현재 구동중인 서버가 있으면 클라이언트 그 서버로 요청 보낼 수 있음! => 응답결과 돌려줌
- 요청과 응답에 의해서 프로그램은 돌아감! ("통신"한다 표현)
- 웹에서의 통신방식 : HTTP 프로토콜 통신
* 자바만을 가지고 서버와 클라이언트 간의 간단한 통신 해보기!!
이때 데이터를 입출력하고자 한다면 서버와 클라이언트 간의 스트림(연결통로)이 필요함!
* 소켓 : 프로세스간의 통신을 담당하는 것! (스트림을 연결하기 위한 문)
* 소켓 프로그래밍 (TCP 방식 / UDP 방식)
- TCP 방식 : 데이터 전송속도가 느림! 데이터가 정확하고 안정적으로 전달 가능함! (신뢰성이 요구되는 프로그램 : http, 이메일) (클라이언트가 요청하고 서버가 응답하는 느낌)
- UDP 방식 : 데이터 전송속도가 빠름! 신뢰성 없는 데이터 전달 될 수 있음! (데이터를 빠른 속도로 전송하고자 하는 프로그램 : 실시간 동영상 서비스) (클라이언트가 일방적으로 요청하는 느낌)
TCP(Transmission Control Protocol)
- 서버, 클라이언트 간의 1 : 1 소켓 통신
- 데이터를 교환하기에 앞서서 서버, 클라이언트가 연결되어있어야함! (서버가 먼저 실행되어 클라이언트의 요청 기다릴꺼임)
- 신뢰성 있는 데이터 전달 가능
* 소켓(Socket)
- 프로세스간의 통신을 담당
- Input / OutputStream을 가지고 있음! (이 스트림을 통해 입출력이 이루어짐)
* Server Socket
- 포트와 연결되어(Bind) 외부의 연결 요청을 기다리다 연결요청 들어오면 수락해줄 용도
수락 => 통신 할 수 있는 Client Socket 생성
Server
package com.kh.chap02_tcp.run;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ServerProgram {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 입력 보조스트림
BufferedReader br = null;
// 한줄씩 읽어오는 출력보조스트림
PrintWriter pw = null;
// 1) 포트 번호 지정 (서버측에서 몇 번 포트로 통로를 열꺼냐)
int port = 3000;
ServerSocket server = null;
try {
// 2) Server Socket 객체 생성시 포트 결합(bind) => (ServerSocket은 클라이언트의 연결 요청을 받아줄 용도의 소켓)
server = new ServerSocket(port);
// 3) 클라이언트로부터 접속 요청이 올 때 까지 대기상태...
System.out.println("클라이언트의 요청을 기다리고 있어요...");
// 4) 연결 요청이 오면 요청 수락 후 해당 클라리언트와 통신 할 수 있는 서버측 소켓 객체 생성
Socket socket = server.accept(); // socket == 클라이언트와 통신할 수 있는 소켓 객체
System.out.println(socket.getInetAddress().getHostAddress() + "가 연결을 요청함...");
// 5) 클라이언트와 입출력 스트림 생성(바이트 스트림으로 밖에 안됨! => 1byte 짜리!) => 성능이 별로 안좋음
// 6) 보조스트림을 통해서 성능 개선
// 입력용 스트림 => 1바이트 짜리 바이트 스트림을 문자스트림으로 변경해줌!! => 성능 더 좋은 보조스트림 껴서
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 출력용 스트림 (클라이언트에게 값을 한 줄 단위로 출력할 수 있는 출력용 스트림)
pw = new PrintWriter(socket.getOutputStream());
// PrintWritter : 데이터 출력 print(), println() 메소드 가지고 있는 보조스트림
// 7) 스트림을 통해 읽고 쓰기
// 클라이언트로부터 전달된 메세지가 있을 경우 서버측 읽어들일거임! (입력)
while(true) {
String message = br.readLine();
System.out.println("클라이언트로 부터 전달받은 메시지 : " + message);
// 반대로 클라이언트에게 데이터 전달 (출력!)
System.out.print(socket.getInetAddress().getHostAddress() + "클라이언트에게 보낼 내용 : ");
String sendMessage = sc.nextLine();
pw.println(sendMessage); // 클라이언트에게 출력
pw.flush(); // 현재 스트림에 있는 데이터를 강제로 내보내는 메소드 => close() 할 때 자동 호출됨
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 8) 통신 종료
try {
pw.close();
br.close();
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Client
package com.kh.chap02_tcp.run;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientProgram {
public static void main(String[] args) {
// 클라이언트용 프로그램
Scanner sc = new Scanner(System.in);
BufferedReader br = null;
PrintWriter pw = null;
Socket socket = null;
// 요청하고자 하는 서버 ip : 자신의 IP 주소, 컴퓨터가 두대가 없으니까 내가 서버와 클라이언트 두개의 역할을 해보자
// 포트번호 : 3000
int port = 3000;
String serverIP;
try {
serverIP = "자신의 IP주소";
// 1) 서버에 연결 요청 보내는 구문 (요청하고자 하는 서버의 IP주소와 지정된 포트번호를 제시하면서 소켓 객체 생성)
socket = new Socket(serverIP, port);
// 서버꺼져있거나 못찾으면 (통신실패) null 이 담김
if(socket != null) {// 서버와 잘 연결됐을 경우
System.out.println("서버와 연결 성공!!");
// 2) 서버와 입출력 기반스트림 생성
// 3) 보조스트림 통해서 성능 개선
// 입력용 스트림
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 출력용 스트림
pw = new PrintWriter(socket.getOutputStream());
while(true) {
// 4) 스트림을 통해 읽고 쓰기
System.out.print("서버에게 보낼 내용 : ");
String sendMessage = sc.nextLine();
pw.println(sendMessage);
pw.flush();
String message = br.readLine();
System.out.println("서버에게 전달받은 메시지 : " + message);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 5) 통신 종료
try {
pw.close();
br.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
실행
먼저 ServerProgram을 실행 한 후 이어서 ClientProgram을 실행한다.
먼저 클라이언트 콘솔에서 보내고 싶은 말을 보내면 Sever에 뜨게된다.
그 후 서버에서도 보내면 클라이언트 콘솔에 출력된다,