본문 바로가기

Etc./APM

소켓프로그래밍이란

1. 소켓이란? 

사전적으로 구멍, 연결, 콘센트 등의 의미를 가진다. 전기를 필요로하는 디바이스 또는 부품들이 전기를 공급받을 수 있도록, 전기 공급 인프라 환경에 연결할 수 있게 만들어진 연결부라고 볼 수 있다.

 

네트워크 프로그래밍에서도 비슷한 의미로 사용된다. 프로그램이 네트워크에서 데이터를 송수신할 수 있도록, "네트워크 환경에 연결할 수 있게 만들어진 연결부"이다. 

= 데이터를 송수신할 수 있는 연결부

 

주로 OSI 7 Layer의 네번째 계층인 TCP상에서 동작하는 소켓을 사용하며, 이를 TCP 소켓이라고 한다. ( UDP를 사용하면 UDP 소켓 )

 

2.1 클라이언트 소켓과 서버 소켓 

소켓을 통해 데이터 통신을 위한 연결을 만들기 위해서는, 연결 요청을 보내는지 또는 요청을 받아들이는지에 따라 소켓의 역할이 나뉘게 되는데, 전자가 클라이언트 소켓이고 후자가 서버 소켓이다.

(역할에 따라서 처리되는 흐름이 다를뿐이다.)

 

2. 2 소켓 API 실행흐름

클라이언트 소켓: 

소켓 생성, 서버에 연결 요청, 데이터 송수신, 소켓 닫음 [create, connect, send/recv, close]

 

서버 소켓:

소켓 생성, 사용할 ip 주소와 포트번호를 생성한 소켓에 결합, 클라이언트로부터 연결 요청이 수신되는지 주시, 요청이 수신되면 받아들여 데이터 통신을 위한 소켓 생성, 데이터 송수신, 소켓 닫음 [create, bind, listen, accept, send/recv, close]

 

3. 클라이언트 소켓 프로그래밍

3.1. 클라이언트 소켓 생성(socket())

소켓 생성시 소켓의 종류를 지정할 수 있는데, TCP 소켓을 위해서는 스트림(Stream)타입, UDP 소켓을 위해서는 데이터그램(Datagram) 타입을 지정할 수 있다.

최초 소켓이 만들어지는 시점ㅁ에는 정보가 없기 떄문에 connect() API를 호출한다.

 

3.2. 클라이언트 소켓 생성(socket())

connect() API는 "IP주소"와 "포트 번호"로 식별되는 대상으로 연결 요청을 보낸다. 호출이 성공하면 send() / recv() API를 통해 데이터를 주고받을 수 있다.

 

3.3. 데이터 송수신 (send()/recv())

연결된 소켓을 통해 데이터를 보낼 때는 send(), 데이터를 받을 때는 recv API를 사용한다. 두 API 모두 block 방식으로 동작한다. 

두 API 모두 실행결과가 결정되기 전까지는 API가 리턴되지 않는다. 

 

send()의 경우 데이터를 보내는 주체가 자기 자신이기 때문에, 데이터의 정보를 알 수 있지만 recv()의 경우 데이터의 정보를 특정할 수 없기 때문에 한번 실행되면 언제 끝날지 모르는 상태가 된다.

 

그러므로 데이터 수신을 위한 recv() API는 별도의 스레드에서 실행되고, 소켓의 생성과 연결이 완료된 후, 새로운 스레드를 하나 만든 다음 그곳에서 recv()를 실행하고 데이터가 수신되길 기다린다. 

 

3.4. 소켓 닫기 (close())

송수신이 필요 없을 때 close() API를 호출한다. 

종료 후 다시 데이터를 주고 받고자 한다면 또 한번의 소켓 생성과 연결 과정을 통해 소켓이 데이터를 송수신할 수 있는 상태가 되어야한다.

 

4. 서버 소켓 프로그래밍

4.1. 서버 소켓 생성(socket())

소켓 생성시 소켓의 종류를 지정할 수 있는데, TCP 소켓을 위해서는 스트림(Stream)타입, UDP 소켓을 위해서는 데이터그램(Datagram) 타입을 지정할 수 있다.

최초 소켓이 만들어지는 시점ㅁ에는 정보가 없기 떄문에 connect() API를 호출한다.

 

4.2. 서버 소켓 바인딩(bind())

TCP, UDP는 하나의 소켓 포트가 필요한데 다른 소켓과 중복시 충돌이 생긴다. bind() API는 해당 소켓이 지정된 포트 번호를 사용할 것이라는 운영체제에 요청하는 API인 것이다. 만약 지정된 포트번호를 다른 소켓이 사용하고 있다면 bind() API는 에러를 리턴한다.

 

4.3. 클라이언트 연결 요청 대기 (listen())

클라이언트에 의한 연결 요청(connet() API)이 수신될 때까지 기다린다. 

listen()의 리턴값으로 판단할 수 있는 것은 클라이언트 요청이 수신되었는지, 에러가 발생했는지이고 클라이언트 연결 요청에 대한 정보는 시스템 내부적으로 관리되는 큐에 쌓이게 된다.

이 시점은 아직 연결이 되지 않은 대기상태이다. 

 

4.4. 클라이언트 연결 수립 (accept())

최종적으로 연결 요청을 받아들이는 역할을 수행하는 것은 accept() API이다.

최종적으로 데이터 통신을 위해 연결되는 소켓이, 앞서 bind() 또는 listen() API에서 사용한 서버 소켓이 아니라 accept API 내부에서 새로 만들어지는 소켓이다.

앞서 bind() 및 listen()을 통해 소켓에 포트 번호를 바인딩하고 요청 대기 큐를 생성하여 클라이언트의 요청을 대기하였다. 그리고 accept() API에서 데이터 송수신을 위한 새로운 소켓을 만들고 서버 소켓의 대기 큐에 싸여있는 첫 번째 연결 요청을 매핑시킨다.

 

4.5. 데이터 송수신 (send()/recv())

 

4.6. 소켓 연결 종료 (close())

 

참고) https://recipes4dev.tistory.com/153

'Etc. > APM' 카테고리의 다른 글

[DB] 프로시저 (procedure)  (0) 2023.01.30
[APM] APM 스카우터  (0) 2023.01.27
OSI 7계층  (1) 2023.01.25
TCP/IP 소켓 프로그래밍 기초 지식  (0) 2023.01.25
WAS란?  (0) 2023.01.05