소켓
- 서버와 클라이언트를 연결하는 출입구.
- 소켓을 통해 데이터 통로가 생성되어 데이터를 주고받을 수 있다.
소켓의 구성
- 프로토콜(Protocal) : TCP/UDP
- IP주소 : 호스트들을 식별할 수 있는 고유 주소.
- 포트번호(Port Number) : 호스트 내의 프로세스들을 식별할 수 있는 번호.
소켓의 종류
- 클라이언트 소켓 : 통신 연결 요청을 보내는 쪽
- 서버 소켓 : 통신 연결 요청을 받아들이는 쪽
소켓 시스템 콜 라이브러리
- socket() : 데이터 전송에 사용되는 소켓을 생성할 때 호출하며, 소켓을 성공적으로 생성하면 소켓 디스럽터를 반환한다.
- bind() : 소켓에 주소를 부여하는 함수이다. 반환된 소켓 디스크립터를 이용하여 상대 프로세스와 통신하려면 먼저 생성된 소켓에 주소를 부여해야 하는데 이때 사용된다.
- listen() : 서버 프로세스에서 실행되며, 소켓에서 대기할 수 있는 클라이언트의 연결 요청 개수를 지정한다. 일반적으로 비연결형 서비스에서는 사용하지 않고 연결형 서비스에서만 사용한다.
- accept() : 이 함수를 실행하여 클라이언트의 요청을 기다리고, 클라이언트 프로세스의 connect() 요청이 발생하면 연결이 설정된다. 클라이언트로부터 연결 요청이 발생하면 둘 사이의 연결이 설정되고, addr에 연결을 요청한 클라이언트의 소켓 주소를 반환한다. 이 값을 확인하면 어느 클라이언트가 연결을 시도했는지 알 수 있고, 연결 요청을 거부할 수도 있다.
서버-클라이언트 프로그래밍
- 네트워크 서비스를 제공하는 서비스 제공자와 서비스 이용자 사이의 관계를 표현
- 서버 프로세스 : 서비스를 제공하는 프로그램
- 클라이언트 프로세스 : 서비스를 제공받는 프로그램
프로그래밍 종류
- 연결형 서비스 : TCP 프로토콜을 사용하는 네트워크 서비스이다. 상대적으로 신뢰성이 높은 서비스로 패킷을 전송하기 전에 미리 연결 설정을 하여 송신한다. 패킷들이 모두 동일한 경로를 이용하기 때문에 목적지에 도착하는 패킷의 순서가 송신된 순서와 동일하다는 특성이 있다.
- 비연결형 서비스 : 연결형 서비스보다 신뢰성이 떨어지는 네트워크 서비스이다. 패킷이 서로 다른 경로를 통해 목적지로 이동하여 도착하는 순서가 일정하지 않다.
연결형 서비스 구현하기
TCP를 이용한 통신 절차는 다음과 같다.
서버의 동작 과정
- 서비스 교신점(호스트의 IP 주소, 포트 번호) 공개
- 클라이언트로부터 발생하는 서비스 요구 대기
- 클라이언트에 서비스 제공
- 해당 클라이언트에 서비스 제공 완료
- 다시 2단계로 이동
클라이언트의 동작
- 원하는 서비스를 제공하는 서버 확인
- 해당 서버와 연결 시도
- 서버에 서비스 요청
- 서비스 이용 완료
자바를 이용하여 서버-클라이언트를 연결하고 간단한 welcome메시지를 보내는 코드를 구현해 보겠다.
- EchoSver.java (서버)
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Main {
public static void main(String[] args) {
try {
//서버소켓 생성
ServerSocket ss = new ServerSocket(8200);
System.out.println("EchoServer is started and waiting for client..");
Socket client = ss.accept();
System.out.println("Client is connected : " + client);
//환영메세지 보내기
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(new OutputStreamWriter(client.getOutputStream())); //출력
out.println("Welcome! This is a EchoServer.");
out.flush(); // flush() 버퍼에 있는 내용 즉각보내기 (= 전송시작)
System.out.println("message is sent.");
while (true) {
String msg = in.readLine();
System.out.println("From Client :" + msg);
if(msg == null) break; //데이터가 비면 멈추게 구현
}catch (IOException e) {
e.printStackTrace(); //에러의 근원지를 찾아 단계별로 출력해줌
}
}
}
실행결과
addr : 나의 컴퓨터 주소
localport : 서버 소켓 포트번호
-EchoClient.java (클라이언트)
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class EchoClient {
public static void main(String[] args) {
Scanner scn = new Scanner(System.in);
try {
//연결요청 보내기
Socket socket = new Socket("127.0.0.1", 8200); //내 컴퓨터 아이피주소, 포트번호
System.out.println("Connection is successfull !!" + socket);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream()));
//수신하기
String msg = in.readLine(); //데이터 수신받는 변수
System.out.println(msg);
while (true) {
System.out.print("Your message : ");
msg = scn.next();
out.print(msg);
out.flush();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
실행결과
클라이언트 프로그램이라 port번호와 localport번호가 바뀐 것을 볼 수 있다.
'네트워크' 카테고리의 다른 글
[네트워크] handler를 이용하여 채팅 구현하기 (0) | 2022.11.22 |
---|---|
[네트워크] 멀티 쓰레드로 채팅 구현하기 (0) | 2022.11.10 |