1. 소켓 프로그래밍이란?
- 소켓 프로그래밍은 소켓을 이용한 통신 프로그래밍을 뜻한다.
- 소켓이란 프로세스간의 통신에 사용되는 양쪽 끝단을 의미한다.
- 자바에서는 java.net 패키지를 통해 소켓 프로그래밍을 지원하는데, 소켓 통신에 사용되는 프로토콜에 따라
다른 종류의 소켓을 구현하여 제공한다.
2. TCP와 UDP
- TCP/IP 프로토콜은 이기종 시스템간의 통신을 위한 표준 프로토콜로 프로토콜의 집합이다.
- TCP와 UDP 모두 TCP/IP 프로토콜에 포함되어 있으며, OSI 7계층의 전송계층에 해당된다.
- TCP와 UDP의 장단점은 아래와 같다.
항목 | TCP | UDP |
연결방식 | connection-oriented - 연결 후 통신(ex 전화기) - 1:1 통신 방식 |
connectionless-oriented - 연결없이 통신(ex 소포) - 1:1, 1:n, n:n 통신방식 |
특징 | 데이터의 경계를 구분안함(byte-stream) 신뢰성 있는 데이터 전송. - 데이터의 전송순서가 보장됨. - 데이터의 수신여부를 확인함. (즉, 손실되면 다시 전송) - 패킷을 관리할 필요가 없음. - 단, UDP보다 전송속도가 느림. |
데이터의 경계를 구분함(datagram) 신뢰성 없는 데이터 전송 - 데이터의 전송순서가 바뀔 수 있음. - 데이터의 수신여부를 확인안함. (즉, 손실되어도 알 수 없음) - 패킷을 관리해주어야 함. - 단, TCP보다 전송속도가 빠름. |
관련 클래스 | Socket ServerSocket |
DatagramSocket DatagramPacket MulticastSocket |
( 위의 장단점을 확인하고 적합한 프로토콜을 선택해서 프로그래밍을 해야한다. )
( TCP는 파일을 주고받을 때 적합하다. )
( UDP는 게임이나 동영상의 데이터를 실시간으로 전송하는 경우에 적합하다. )
3. TCP 소켓 프로그래밍
- TCP 소켓 프로그래밍은 클라이언트와 서버간의 일대일 통신이므로, 서버 프로그래밍이 실행되어
클라이언트 프로그램의 연결 요청을 기다리고 있어야 한다.
- 과정은 아래와 같다.
순서 | 설명 |
1 | 서버 프로그램에서는 서버 소켓을 사용해서 서버 컴퓨터의 특정 포트에서 클라이언트의 연결 요청을 처리할 준비를 한다. |
2 | 클라이언트 프로그램은 접속할 서버의 IP 주소와 포트 정보를 가지고 소켓을 생성해서 서버에 연결을 요청한다. |
3 | 서버 소켓은 클라이언트의 연결요청을 받으면 서버에 새로운 소켓을 생성해서 클라이언트의 소켓과 연결되도록 한다. |
4 | 이제 클라이언트의 소켓과 새로 생성된 서버의 소켓은 서버 소켓과 관계없이 일대일 통신을 한다. |
( 서버 소켓은 포트와 결합(bind)되어 포트를 통해 원격 사용자의 연결요청을 기다리다가 연결요청이 올 때마다
새로운 소켓을 생성하여 상대편 소켓과 통신할 수 있도록 한다. 여기 까지가 서버 소켓의 역할이다. )
( 그러므로, 실제적인 데이터 통신은 서버 소켓과 관계없이 소켓과 소켓 간에 이루어진다. )
( 여러 개의 소켓이 하나의 포트를 공유해서 사용할 수 있지만, 서버 소켓은 다르다. )
( 서버 소켓은 포트를 독점하기 때문에, 만일 한 포트를 둘 이상의 서버소켓과 연결하는 것이 가능하다면 클라이언트
프로그램이 어떤 서버소켓과 연결되어야 하는지 모를 것이다. )
( 단, 두 서버 소켓이 서로 다른 프로토콜을 사용하는 경우에는 같은 포트를 사용할 수 있다. )
( 여기서 포트는 host가 외부와 통신을 하기 위한 통로로 하나의 호스트가 65536개의 포트를 가지고 있다. )
( 포트는 번호를 구분짓는데, 0~65535의 범위를 가진다. )
( 보통 1023번 이하의 포트는 FTP나 Telnet과 같은 기존의 다른 통신 프로그램들에 의해서 사용되는 경우가 많기
때문에 1023번 이상의 번호 중에서 사용하지 않는 포트를 골라야 한다. )
( 정리하면, 서버 소켓은 소켓간의 연결만 처리하고 실제 데이터는 소켓들끼리 주고 받는다.)
( 그러므로, 소켓은 두 개의 스트림인 입력과 출력 스트림을 가지고 있으며, 이 스트림들은 연결된 상대편 소켓의
스트림들과 교차 연결된다. )
( 즉, 각 소켓의 OutputStream으로 나간 것은 상대편 소켓의 InputStream으로 연결된다는 것이다. )
3-1. TCP 소켓 프로그래밍을 이해하기 위한 예제(1)
: 간단한 TCP/IP 서버 프로그램을 구현한 예제이다.
package Networking;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Exercise006 {
public static void main(String args[]) {
ServerSocket serverSocket = null;
try {
// 서버소켓을 생성하여 7777번 포트와 결합(bind)시킨다.
serverSocket = new ServerSocket(7777);
System.out.println(getTime()+"서버가 준비되었습니다.");
} catch(IOException e) {
e.printStackTrace();
}
while(true) {
try {
System.out.println(getTime()+"연결요청을 기다립니다.");
// 서버소켓은 클라이언트의 연결요청이 올 때까지 실행을 멈추고 계속 기다린다.
// 클라이언트의 연결요청이 오면 클라이언트 소켓과 통신할 새로운 소켓을 생성한다.
Socket socket = serverSocket.accept();
System.out.println(getTime()+ socket.getInetAddress() + "로부터 연결요청이 들어왔습니다.");
// 소켓의 출력스트림을 얻는다.
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
// 원격 소켓(remote socket)에 데이터를 보낸다.
dos.writeUTF("[Notice] Test Message1 from Server.");
System.out.println(getTime()+"데이터를 전송했습니다.");
// 스트림과 소켓을 닫아준다.
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // while
} // main
// 현재시간을 문자열로 반환하는 함수
static String getTime() {
SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
return f.format(new Date());
}
} // class
( 서버 소켓은 7777번 포트에서 클라이언트 프로그램의 연결요청을 기다린다. )
3-2. TCP 소켓 프로그래밍을 이해하기 위한 예제(2)
: 간단한 위 예제와 맞게 클라이언트 프로그램을 구현한 예제이다.
package Networking;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.net.Socket;
public class Exercise007 {
public static void main(String args[]) {
try {
String serverIp = "127.0.0.1";
System.out.println("서버에 연결중입니다. 서버IP :" + serverIp);
// 소켓을 생성하여 연결을 요청한다.
Socket socket = new Socket(serverIp, 7777);
// 소켓의 입력스트림을 얻는다.
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
// 소켓으로 부터 받은 데이터를 출력한다.
System.out.println("서버로부터 받은 메시지 :"+dis.readUTF());
System.out.println("연결을 종료합니다.");
// 스트림과 소켓을 닫는다.
dis.close();
socket.close();
System.out.println("연결이 종료되었습니다.");
} catch(ConnectException ce) {
ce.printStackTrace();
} catch(IOException ie) {
ie.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
} // main
} // class
( 서버 프로그램이 작동하지 않는다면 ConnectException이 발생한다. )
( 또한 서버와의 작업이 끝나면 소켓과 스트림을 닫아야 한다. )
다음장
'자바 > 네트워킹' 카테고리의 다른 글
소켓 프로그래밍: TCP와 UDP(4) (0) | 2022.05.02 |
---|---|
소켓 프로그래밍: TCP와 UDP(3) (0) | 2022.05.02 |
소켓 프로그래밍: TCP와 UDP(2) (0) | 2022.05.02 |
네트워킹(Networking) (2) - URL, URLConnection (0) | 2022.04.30 |
네트워킹(Networking) (1) - InetAddress (0) | 2022.04.30 |