
[서버] [클라이언트]
socket() socket()
bind()
listen()
accept() ←————————————————— connect()
read() / write() ———————— write() / read()
close() close()
개념을 정리하고 글을 계속 읽어보는데 파일 디스크립터라는 말이 계속 나왔다. 이전 글에서 정리할 때 표준 입출력 0,1 표준에러 2 이렇게만 알고 있었는데 정확히 이해가 안되서 한번 더 정리하고자 한다.
일단 이전 글이랑 초반 설명은 같습니다.
운영체제가 만든 파일(그리고 소켓)을 구분하기 위한 일종의 숫자
저 수준 파일 입출력 함수는 입출력을 목적으로 파일 디스크립터를 요구함
저 수준 파일 입출력 함수에게 소켓의 파일 디스크립터를 전달하면, 소켓을 대상으로 입출력 진행
| 파일 디스크립터 | 대상 |
|---|---|
| 0 | 표준 입력 : Standard Input |
| 1 | 표준 출력: Standard Output |
| 2 | 표준 에러 : Standard Error |
근데 여기서 표 내용을 위주로 기억을 하고 있었는데, 다시 보니 운영체제가 만든 파일을 구분하기 위한 일종의 숫자라고 합니다. 다시 말해 소켓을 구분하기 위한 숫자로도 사용이 가능합니다.
표를 다시 그려보면,
| 파일 디스크립터 | 대상 |
|---|---|
| 0 | 표준 입력 : Standard Input |
| 1 | 표준 출력: Standard Output |
| 2 | 표준 에러 : Standard Error |
| 3~ | open/socket 호출 시 여기서부터 순서대로 발급 |
sockfd에 생성한 소켓을 저장하면, OS가 sockfd에 3번이라는 번호를 발급합니다.
write, read, close는 어떤 소켓에 작업을 할 것인지에 따라 알맞는 sockfd 번호를 넣어주면 됩니다.
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
// sockfd = 3 (OS가 발급한 번호)
write(sockfd, buf, len); // "3번한테 데이터 써"
read(sockfd, buf, len); // "3번한테서 데이터 읽어"
close(sockfd); // "3번 반납"
파일 디스크립터에 집중하여, TCP 서버및 클라이언트에 관한 함수들을 다시 정리해보겠습니다.
int socket(int domain, int type, int protocol); // fd 발급
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr* myaddr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen); // 새 fd 반환
int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen);
#include <unistd.h>
int open(const char* path, int flag); // 성공 시 fd 반환
int close(int fd); // open() 과 함께, fd 반납
ssize_t write(int fd, const void* buf, size_t nbytes);
ssize_t read(int fd, void* vuf, sizet nbytes);