여러 대의 컴퓨터를 통신 회선으로 연결한 것(홈 네트워크, 지역 네트워크, 인터넷 등이 해당)
여러 통신기기들을 서로 연결하여 데이터를 손쉽게 주고받거나 자원 등을 공유하기 위해 사용
소켓을 이용한 통신 프로그래밍
소켓(Socket)
프로세스 간의 통신에 사용되는 양쪽 끝 단
프로토콜(Protocol)
컴퓨터 간의 정보를 주고 받을 때의 통신방법에 대한 규약으로 접속이나, 전달방식, 데이터의 형식, 검증 방법 등을 맞추기 위한 약속
TCP(Transmission Control Protocol)
데이터의 전달의 신뢰성을 최대한 보장하기 위한 방식으로 연결지향형 통신이다.
순차적으로 데이터를 전송하고 확인 및 오류 시 재전송을 한다.
UDP(User Datagram Protocol)
데이터의 빠른 전달을 보장하기위한 방식으로 비연결 지향형 통신이다.
확인 및 재전송 작업이 없다
클라이언트와 서버간의 1:1 소켓 통신
서버가 먼저 실행 되어 클라이언트의 요청을 기다려야 하고 서버용 프로그램과 클라이언트용 프로그램을 따로 구현해야 함
자바에서는 TCP 소켓 프로그래밍을 위해 java.net패키지에서 ServerSocket과 Socket클래스 제공

UDP는 연결 지향적이지 않기 때문에 연결 요청을 받아줄 서버 소켓이 필요 없음
java.net패키지에서 제공하는 두 개의 DatagramSocket간에 DatagramPacket으로 변환된 데이터 주고 받음

class ServerRun
package edu.kh.network.run;
import edu.kh.network.model.service.TCPServer;
public class ServerRun {
public static void main(String[] args) {
TCPServer server = new TCPServer();
server.serverStart();
}
}
class TCPServer
package edu.kh.network.model.service;
import java.io.*;
import java.net.*;
import java.sql.Date;
import java.text.SimpleDateFormat;
public class TCPServer {
// Server : 서비스를 제공하는 프로그램 또는 컴퓨터
// Client : 서버에 서비스를 요청하여 사용하는 프로그램 또는 컴퓨터
// TCP Socket 프로그래밍
// TCP : 데이터 전달의 신뢰성을 최대한 보장하기 위한 방식(연결 지향형 통신)
// 순차적으로 데이터를 전달하고 확인 및 오류 시 재전송
// Socket : 프로세스의 통신에 사용되는 양 끝단 서버와 클라이언트가 통신을 하기 위한 매개체
// ServerSocket : 사바용 소켓
// - Port와 연결되어 외부 요청을 기다리는 역할
// -> 클라이언트 요청이 올 경우 이를 수락(accept)하고 클라이언트가 사용할 수 있는 소켓을 생성
// --> 서버 소켓과 클라이언트 소켓이 연결되어 데이터 통신이 가능해짐
public void serverStart() {
// 1. 서버의 포트번호 정함
int port = 8500; // port 번호는 0~65535 사이 지정 가능
// 단, 1023번 이하는 이미 사용중인 경우가 많으니 제외
// * 사용할 변수를 미리 선언 *
ServerSocket serverSocket = null; // 서버 소켓 저장 변수
Socket clientSocket = null; // 클라이언트 소켓 저장 변수
InputStream is = null; // 클라이언트 -> 서버 입력용 스트림 변수
BufferedReader br = null; // 입력용 보조 스트림 변수
OutputStream os = null; // 서버 -> 클라이언트 출력용 스트림 변수
PrintWriter pw = null; // 출력용 보조 스트림 변수
try {
// 2. 서버용 소켓 객체 생성
serverSocket = new ServerSocket(port); // 서버용 소켓 생성하여 포트 결합
// 3. 클라이언트 쪽에서 접속 요청이 오길 기다림
// - 서버용 소켓은 생성되면 클라이언트 요청이 오기 전까지 다음 코드를 수행하지 않고 대기하고 있음
System.out.println("[Server]");
System.out.println("클라이언트 요청을 기다리고 있습니다");
// 4. 접속 요청이 오면 요청 수락 후 해당 클라이언트에 대한 소켓 객체 생성
// -> 요청을 수락하면 자동으로 Socket 객체가 얻어와짐
clientSocket = serverSocket.accept();
// 접속한 클라이언트의 IP를 얻어와 출력
String clientIP = clientSocket.getInetAddress().getHostAddress();
System.out.println(clientIP + "가 연결을 요청함..");
// 5. 연결된 클라이언트와 입출력 스트림 생성
is = clientSocket.getInputStream();
os = clientSocket.getOutputStream();
// byte 기반이라 너무 약하기에 보조 스트림을 통해서 단단하게 만들어주자
// 6. 보조 스트림을 통해 성능 개선
br = new BufferedReader(new InputStreamReader(is));
// InputStreamReader : 문자기반 스트림과 바이트기반 스트림 연결에 사용되는 스트림
pw = new PrintWriter(os);
// 7. 스트림을 통해 읽고 쓰기
// 7-1) 서버 -> 클라이언트에게 출력(메세지 전송)
Date now = new Date(port); // 생성된 시간을 기록하고 이쓴ㄴ 시간 관련 객체
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(now); // now에 저장된 시간 포멧을 변경
pw.println(time + "[서버 접속 성공]");
pw.flush(); // 스트림에 있는 내용을 모두 밀어냄(마치 close()처럼)
// 7-2) 클라이언트 -> 서버에게 입력(메세지 전송 받기)
String message = br.readLine(); // 클라이언트 메세지 한 줄을 읽어옴
System.out.println(clientIP + "가 보낸 메세지 : " + message);
} catch(IOException e) {
e.printStackTrace(); // 예외 추적
} finally {
// 8. 통신 종료
// 사용한 스트림, 소켓 자원을 모두 반환(close)
try {
// 보조스트림 close시 연결된 기반 스트림(is, os)도 같이 close 됨
if(pw!=null) pw.close();
if(br!=null) br.close();
if(serverSocket != null) serverSocket.close();
if(clientSocket != null) serverSocket.close();
// if문에 {}를 사용 안 하면 다음 한 줄(세미콜론 기준)이 if 내부 코드가 된다
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
