TCP/IP socket

minseok·2023년 8월 30일
0
post-thumbnail

Mac OS에서 C언어를 기반으로 하는 학습은 피곤하다.(읽는 책마다 Window + Visual Studio 기반이다.)
그래서 Docker로 Ubuntu를 올려서 학습해본다!

Linux에서는 file, socket을 다루는 API가 동일하다.

...

File Descriptor

리눅스 기준 파일/소켓에 부여된 정수를 의미

0 : 표준입력 Standard Input
1 : 표준출력 Standard Output
2 : 표준에러 Standard Error

[0, 1, 2]는 이미 입력, 출력, 에러용으로 사용하는 중이다.
추가적으로 소켓이나 파일을 생성하고 descriptior를 얻으면 3부터 얻는다.

입력과 출력은 동시에 불가능하다.

소켓의 타입

송수신 소켓에는 내부적으로 버퍼가 존재한다.

SOCK_STREAM(연결지향형 소켓)

1: 연결지향형 : 데이터가 소멸되지 않음을 보장받는다.
2: 데이터의 경계가 없음 : write 함수 3번으로 100메가를 보내면 read함수 1번으로 100메가를 수신할 수 있다. (버퍼의 데이터 read, write 호출 횟수가 크게 중요하지 않음)
3. 버퍼도 확인하면서 데이터를 전송함

SOCK_DGRAM(비 연결지향형 소켓)

1: 전송된 순서에 상관없이 가장 빠른 전송을 지향한다.
2: 데이터 손실 우려, 파손 우려
3: 전송되는 데이터의 경계가 존재 : 예로 2번 write하면 2번 read를 해야한다.
3: 한 번에 전송할 수 있는 데이터 크기가 존재

소켓 함수호출 순서

생성 -> 주소할당 -> 연결요청 대기상태 -> 연결허용 -> 데이터 송수신 -> 종료
socket() -> bind() -> listen() -> accept() -> read()/write() -> close()


listen()함수가 호출되어야 클라이언트가 연결요청을 할 수 있는 상태가 된다.

listen(int sock, int backlog)
sock : 대기상태에 두고자 하는 소켓의 파일 디스크립터
backlog : 연결요청 대기 큐의 크기정보, 5가 전달되면 클라이언트의 요청 5개까지 대기시킬 수 있음 (잦은 연결요청이 필요한 경우 더 큰 값이 필요)

클라이언트의 연결요청도 인터넷을 통해서 흘러 들어오는 데이터의 전송
Server Socket을 연결요청을 담을 Socket으로 사용한다.
이후 실제 데이터를 주고받을 때는 새로운 Socket을 하나 더 만들어
클라이언트와 자동으로 연결시켜 준다.

accept(int sock, struct socket addr, socklen_t addrlen)
sock : 대기상태에 두고자 하는 소켓의 파일 디스크립터
addr : 클라이언트의 주소정보를 담을 포인터
addrlen : 주소 크기를 담을 포인터

대기 큐가 찰 때까지, accept함수는 데이터 송수신 소켓의 파일 디스크립터를 반환하지 않고 blocking한다.

TCP Client 함수호출 순서

생성 -> 연결요청 -> 데이터 송수신 -> 연결종료
socket() -> connect() -> read()/write() -> close()

int connect(int sock, struct sockaddr * servaddr, socklen_t addrlen)
sock : 클라이언트 소켓의 파일 디스크립터
servaddr : 연결요청 할 서버의 주소정보 구조체 포인터
socklen_t : 주소의 변수 크기

Server Socket과정과의 차이점은 connect()이다.
소켓을 생성한 후 서버로 연결을 요청하는 과정이며 Server Socket이 listen()을 호출한 이후부터 연결요청을 성공할 수 있다.

Server Socket은 listen()을 호출해야 대기 큐를 만든다.

connect()함수가 호출되면 둘 중 한가지 상황이 된다.
1. 연결요청 접수완료 (accept 함수호출을 의미하는 것은 아니며 대기 큐에 등록된 것)
2. 연결요청 중단

profile
즐겁게 개발하기

0개의 댓글