TCP 서버 - 클라이언트 개념

서버 - 클라이언트 예시
웹 서버와 웹브라우저가 동작하는 모습
브라우저는 사용자가 입력한 주소를 해석하여 대기중인 웹서버 접속
-> HTTP 이용하여 요청 보냄
-> 서버는 웹브라우저에서 받은 요청을 분석 후 HTTP를 이용해 응답
-> 브라우저는 서버에서 받은 데이터를 처리해 화면에 표시
웹 서버 - 클라이언트 는 대표적인 TCP 서버 - 클라이언트 응용 프로그램이다.
TCP서버의 핵심동작
1. 서버는 먼저 실행하여 클라이언트 접속을 기다린다 listen( )
2. 클라이언트는 서버에 접속 connect( ) 하여 데이터를 보낸다 send( )
3. 서버는 클라이언트 접속을 수용 accept( ) 하고 클라이언트가 보낸 데이터를 받아 recv( ) 처리한다.
4. 서버는 처리한 데이터를 클라이언트에 보낸다 send( )
5. 클라이언트는 서버가 보낸 데이터를 받아서 recv( ) 처리한다.
6. 데이터를 주고받는 과정을 모두 마치면 접속을 끊는다. close( )

TCP 서버 - 클라이언트 동작원리

서버는 소켓을 생성한 후 클라이언트의 접속대기
서버 소켓은 특정 결합된 포트 번호가 있어 이 포터 번호로 접속하는 클라이언트만 수용할 수 있다.
클라이언트 서버접속
TCP 프로토콜 수준에서 연결 설정을 위한 패킷 교환이 일어난다.
TCP 연결 시 세개의 파일을 주고 받음 SYN,SYN / ACK,ACK 라고 부른다

TCP 수준에서 연결 절차가 끝나면 서버는 접속한 클라이언트와 통신할 수 있는 소켓 생성
새로운 소켓을 이용해 통신한다.
기존 소켓은 다른 클라이언트 접속을 위해 대기 소켓
두 클라이언트도 접속 가능하다.
기존의 소켓은 새로운 클라이언트를 위해 대기한다.

서버와 클라이언트 소켓은 일대일로 대응한다
하나의 클라이언트가 둘 이상의 소켓을 사용하여 서버에 접속 할 수 있다.
TCP 서버 - 클라이언트 분석
- 프로그램 관점에서 소켓은 운영체제의 TCP/IP 구현에서 제공하는
데이터 구조체를 참조하기 위한 매개체이다. - 응용 프로그램이 통신하려면 결정되어야 하는 요소
- 프로토콜 : 통신 규약으로 소켓을 생성할 때 결정한다.
- 지역 : IP주소와 지역포트번호 (서버 또는 클라이언트의 주소)
- 원격 : IP주소와 지역포트번호 (서버 또는 클라이언트가 통신하는 주소)
TCP서버 함수

1. socket( )
-> 함수로 소켓을 생성하므로써 사용할 프로토콜을 결정한다.
2. bind( )
-> 소켓의 지역 ip 주소와 지역 포트 번호를 결정한다.
3. listen( )
-> 소켓의 TCP 상태를 LISTENING 상태로 변경한다.
4. accept( )
-> 클라이언트 접속을 수용, 클라이언트와 통신할 새로운 소켓을 생성한다.
-> 원격 ip 주소와 원격 포트번호가 결정된다.
5. send( ), recv( )
-> 데이터 전송 함수로 통신을 수행한 수 close( )로 함수 소켓을 닫는다.
6. 새로운 클라이언트 접속이 들어올 때 마다 4~5 과정을 반복한다.
bind( ) 함수
소켓의 지역 IP주소와 지역 포트번호를 설정한다
C
#include <sys/type.h>
#include <sys/socket.h>
int bind (
① int sock
② const struct sockaddr *addr
③ socklen_t addrlen
);
1. 클라이언트 접속을 수용하는 소켓으로 지역ip, 포트번호가 아직 결정되지 않은 상태
2. 소켓 주소 구조체로 통신 프로토콜에 따른 주소 정보를 담고 있다
-> TCP/IP 의 경우 sockaddr_in ,sockaddr_in6 지역 주소ip와 포트번호를 초기화하여 전달함
3. 소켓 주소 구조체의 길이 (바이트)
listen( ) 함수
소켓의 TCP 상태를 LISTENING 으로 바꾼다.
LISTENING -> 클라이언트 접속을 받아들일 수 있는 상태가 되었다는 의미
C
#include <sys/type.h>
#include <sys/socket.h>
int listen (
① int sock
② int backlog
);
1. 클라이언트 접속을 수용하는 소켓으로 이전에 bind( ) 함수를 호출하여
지역 IP주소와 지역 포트번호를 설정한 상태이다.
2. 접속가능한 클라이언트의 개수 클라이언트의 접속 정보는 연결큐에 저장된다
backlog 는 이 연결큐의 길이를 나타낸다.
지원 가능한 최대 값은 SOMAXCONN
accept( ) 함수
- 클라이언트의 접속을 수용하고, 접속한 클라이언트와 통신할 수 있는
새로운 소켓을 생성하여 리턴한다. - 클라이언트의 주소 정보 (서버입장에서 원격IP)도 함수 인수를 통해 얻을 수 있다.
C
#include <sys/type.h>
#include <sys/socket.h>
int accept (
① int sock
② struct sockaddr *addr
③ socklen_t *addrlen
);
1. 클라이언트 접속을 수용하는 소켓이다. 이전에 bind( ) 함수로 지역 IP주소와
포트번호를 설정하고 listen( ) 함수로 TCP 상태를 LISTENING 상태로 만든다.
2. 소켓 주소 구조체를 전달하면 접속한 클라이언트의 주소정보로 채워진다.
3. addr 이 가리키는 소켓 주소 구조체의 크기로 초기화 하여 전달한다
accept( ) 함수가 리턴하면 *addrlen에는 accept( )함수가 채워넣은 주소의 크기(바이트)가 저장된다.
TCP 클라이언트 함수
1. socket( )
-> 함수로 소켓을 생성함으로써 사용할 프로토콜을 결정한다.
2. connect( )
-> 함수로 서버에 접속한다. 원격 포트번호, 원격IP주소, 지역 포트번호, 지역IP주소 를 결정한다
3. send( ), recv( )
-> 데이터 전송 함수로 서버와 통신한 후 close( ) 함수로 닫는다.
connect( ) 함수
TPC 프로토콜 수준에서 서버와 논리적 연결을 설정
C
#include <sys/type.h>
#include <sys/socket.h>
int connect (
① int sock
② struct sockaddr *addr
③ socklen_t *addrlen
);
1. 서버와 통신하는 소켓
2. 소켓 주소 구조체 (sockaddr_in)를 서버주소로 초기화 하여 전달한다.
3. 소켓의 주소길이 (바이트)
bind( ) 함수를 호출하지 않음
connetc( ) 함수를 호출하면 운영체제가 자동으로 지역IP주소와 포트번호를 할당해준다.
TCP 데이터 전송 함수
지역, 원격 주소정보 이외 데이터 송수신 버퍼가 있다.
송신버퍼 : 데이터를 전송하기 전 임시로 저장하는 영역
수신버퍼 : 데이터를 프로그램이 읽어가기 전까지 임시로 저장해두는 영역
소켓버퍼 : send( ), recv( ) 는 소켓버퍼에 접근하는 함수
send( ) 함수
C
#include <sys/type.h>
#include <sys/socket.h>
int send(
① int sock
② const void *buf
③ size_t len
④ int flag
);
1. 통신할 대상과 연결 된 소켓
2. 보낼 데이터를 담고 있는 응용 프로그램 버퍼의 주소
3. 보낼 데이터의 크기
4. send( ) 함수의 동작을 바꾸는 옵션 거의 항상 0을 사용한다.
recv( ) 함수
C
#include <sys/type.h>
#include <sys/socket.h>
int recv(
① int sock
② void *buf
③ size_t len
④ int flag
);
1. 통신할 대상과 연결ㄹ된 소켓이다
2. 받은 데이터를 저장할 응용 프로그램 버퍼 주소
3. 운영 체제 수신버퍼로부터 복사할 최대 데이터의 크기
-> 이 값은 buf 가 가리키는 응용 프로그램 보다 크지 않아야한다.
4. recv( ) 함수의 값을 바꾸는 옵션
- MSG_PEEK : 수신 버퍼에 데이터가 계속 남는다.
- MSG_WAITALL : len크기 만큼 데이터가 수신 버퍼에 도착해서
응용프로그램 버퍼에 전부 복사할 때 까지 기다린다.
-> recv( ) 함수의 기본 동작은 수신 버퍼의 데이터를 최대 len 크기만큼
응용 프로그램 버퍼에 복사한 후 해당 데이터를 수신 버퍼에서 삭제하는 것이다
수신버퍼가 len보다 작으면 데이터가 다 도착하지 않아도 현재 있는 만큼만 데이터를 복사하고 리턴함
recv 함수는 두 종류의 성공적인 리턴이 있음
-1 수신 버퍼에 데이터가 도달한 경우
len보다 크지 않은 범위에서 응용 프로그램 버퍼에 최대한 복사 한후 실제 복사한 바이트 수를 리턴함
-> 이 경우 recv( )의 리턴값은 최소 1 최대 len 임
-2
접속을 정상 종료한 경우
close로 호출하여 정상종료 하면 패킷 교환 절차가 일어난다
-> 이 경우 recv( ) 의 리턴값은 0을 리턴한다
recv 함수 사용 시 len으로 지정한 것보다 적은 데이터가 응용 프로그램 버퍼에 복사 될 수 있다.
-> TCP 가 데이터 경계를 구분하지 않아서 발생
받아야하는 데이터의 크기를 알고 있다면 다 받을 때 까지 기다리도록 WAITALL 을 사용하면 좋다.
'리눅스 소켓 프로그래밍 TCPIP' 카테고리의 다른 글
| UDP 서버 - 클라이언트 (0) | 2024.12.16 |
|---|---|
| 멀티 스레드 : 리눅스 (3) | 2024.12.16 |
| 소켓 주소 구조체 다루기 (3) | 2024.12.13 |
| 소켓 시작하기 (0) | 2024.12.12 |
| 리눅스 - 네트워크와 소켓 프로그래밍 (0) | 2024.12.12 |