본문 바로가기

프로그래밍/서버

소켓 프로그래밍 1

블로킹 소켓(Blocking Socket)

 : 소켓에 대한 동기 입출력 방식

 

블로킹

 : 디바이스에 처리 요청을 걸어 놓고 응답을 대기하는 함수를 호출할 때 스레드에서 발생하는 대기 현상

 

송신 버퍼(send buffer)

 : 일련의 바이트 배열

 송신 버퍼의 크기는 고정되어 있지만, 마음대로 크기를 변경할 수 있다

 송신 버퍼는 FIFO 형태로 작동한다

 

 send(data)를 호출하면 송신 버퍼에 채워진다

 송신 버퍼에 채워진 data는 잠시 후 통신 선로를 통해 빠져나간다

 따라서 송신 버퍼는 뭔가가 채워지더라도 곧 빈 상태가 된다

 

송신 버퍼가 가득 차면 send() 함수의 블로킹이 발생한다

송신 버퍼가 수용가능한 상태가 될 때까지 대기한다

 

TCP 수신 함수 : recv()

 

1바이트라도 수신할 수 있으면 즉시 리턴한다

비어있으면 채워질 때까지 블로킹한다

 

수신 버퍼가 꽉 차면 TCP로 데이터를 보내는 쪽에서는 송신 함수인 send()가 블로킹된다

 

TCP 송신 속도느린 쪽에 맞추어 작동한다

ex) 

 송신 버퍼에 데이터를 채우는 속도보다 수신 함수가 데이터를 꺼내는 속도가 느리면

수신 함수가 데이터를 꺼내는 속도에 맞춰진다

 

TCP는 송신자가 초당 보내는 데이터양이 수신자가 초당 수신할 수 있는 데이터양보다 많을 때 송신자 측 OS가 알아서 초당 송신량을 줄인다

 

UDP는 송신 함수로 송신 버퍼에 데이터를 쌓는 속도보다 수신 함수로 수신 버퍼에서 데이터를 꺼내는 속도가 느리면, 데이터그램 유실이 발생한다

 

논블록 소켓을 사용하는 방법

 

1. 소켓을 논블록 소켓으로 모드 전환한다

 

2. 똑같이 송신, 수신, 연결과 관련된 함수를 호출한다

 

3. 함수 호출에 대해 즉시 리턴하는데 리턴 값을 '성공' 또는 'would block' 오류 둘 중 하나이다

 

would block은 블로킹이 걸렸어야 할 상황인데 블로킹이 걸리지 않았다는 것을 의미한다

 

-> 많은 수의 소켓 데이터를 지연 시간없이 처리할 수 있다

 

0바이트 송신

 : 0바이트를 보내려는 시도를 하는데, 송신하는 함수가 '성공'을 리턴하면 TCP 연결되어 있다는 의미이다

 ENOTCONN(소켓이 연결되어 있지 않음)을 리턴하면 TCP 연결이 진행 중이다

 기타 오류 코드가 나오면 TCP 연결 시도가 실패한 것이다

 

select() 함수의 매개변수로 소켓의 배열대기 최대 시간을 넣는다

 

sockets에 I/O 처리가 가능한 소켓이 하나라도 있을 경우 즉시 리턴한다

 

소켓 안의 송신 버퍼에 1바이트라도 공간이 남았거나 소켓 안의 수신 버퍼에 1바이트라도 들어 있다면 'I/O 가능'이라 한다

 

select()를 갖고 리스닝 소켓에서 I/O 가능 이벤트가 탐지되면 accept()를 호출한다

들어온 TCP 연결에 대한 소켓 핸들을 얻게 된다

 

논블록 소켓의 장점

 

1. 스레드 블로킹이 없으므로 중도 취소 같은 통제가 가능하다

 

2. 스레드 개수가 1개이거나 적어도 소켓을 여러개 다룰 수 있다

 

3. 스레드 개수가 적거나 1개이므로 연산량이 낭비되지 않는다. 또 호출 스택 메모리도 낭비되지 않는다

 

단점

 

1. would block인 경우 재시도 호출 낭비가 발생한다

 

2. 입력하는 데이터 블록에 대한 복사 연산이 발생한다

 

3. connect() 함수는 재시도 호출을 하지 않지만, send(), receive() 함수는 재시도 호출해야 하는 API가 일관되지 않는다는 문제가 있다

 

수신 버퍼에 1바이트라도 들어 있으면 I/O 가능이 되는데, 이 상태에서 recv() 함수를 호출하면 수신 버퍼에 있는 것을 꺼내온다

따라서 would block이 생기지 않으면 UDP 소켓의 receive() 처리 역시 문제가 없다

 

하지만 UDP 소켓의 send() 처리에서는 문제가 있다

 

UDP 소켓의 송신 버퍼에 1바이트라도 비어 있으면 I/O 가능이다. 그런데 보내려는 데이터가 5바이트인데 송신 버퍼 빈 공간이 1바이트라면, 넣을 수 있는 크기를 넘는다. 

UDP는 TCP와 다르게 일부만 보낼 수 없으므로 would block이 발생한다.

I/O 가능이라 재시도를 하지만 여전히 would block이다

상황이 반복되면 UDP send()를 하지 못한채 계속 반복된다 -> CPU 낭비로 이어진다

 

4. 소켓 함수 내부의 데이터 복사 부하가 발생한다

 

'프로그래밍 > 서버' 카테고리의 다른 글

소켓 프로그래밍 3  (0) 2019.09.27
소켓 프로그래밍 2  (0) 2019.09.25
컴퓨터 네트워크 2  (0) 2019.09.20
컴퓨터 네트워크 1  (0) 2019.09.19
멀티스레딩  (0) 2019.09.14