서버 측
- 소켓 생성
- 네트워크 인터페이스와 결합(bind) 어느 IP와 연결할지
- bind 후에 listen 함수로 백로그 큐 크기를 설정
- 클라이언트 연결 요청 대기 및 수락을 반복
- 연결 대기와 연결 수락하는 작업은 accept함수가 한다 (클라이언트 연결 요청을 대기하는 소켓)
- accept함수는 클라이언트와 통신할 소켓을 또하나 만들고 반환 (송수신하는 소켓)
클라이언트 측
- 소켓생성
- 인터페이스 결합(bind) 생략가능하다.
- 누구한테 연결할지를 connect함수로(서버:IP와 Port로 connect시도)
- 메시지 전송은 send, 수신은 recv로한다.
- 소켓닫기
서버
bind
int bind(int socket, struct sockaddr* localAddress, unsinged int addressLength)
- 첫번째 socket은 이전의 socket()호출에서 반환된 식별자
- 두번쨰 localAddress는 주소 파라미터로 sockaddr의 포인터 자신의 해당 인터페이스 및 요구를 기다리는 포트 번호를 포함하는 sockaddr_in의 구조체 가리키면 된다.
- 세번째 주소 구조체의 길이 sizeof(struct sockaddr_in)
listen
int listen(int socket, int queueLimit)
- 첫번째 socket은 사용할 소켓 즉, 식별자
- 두번째 queueLimit은 연결 요구 개수의 최대값을 지정
- 주어진 소켓에 대해 내부 상태의 변경을 유발하여 들어오는 tcp연결 요구들이 프로그램에 의해 처리되고 받아들여질 수 있도록 큐에 저장
- 대기만 하는 것 연결하는 함수가 아니다.
accept
int accept(int socket, struct sockaddr* clientAddress, unsigned int* addressLength)
- socket을 위한 큐에서 다음 연결을 하나 꺼낸다. 만약 큐가 비어 있다면 요구가 도착할 때까지 블록
- 성공하면 clientAddress가 가리키는 sockaddr구조체를 연결의 다른 종단점에 있는 클라이언트의 주소로 채운다.
클라이언트
connect()
- 클라이언트가 서버와 연결을 설정하기 위해서는 소켓에 connect() 호출
int connect(int socket, struct sockaddr* freodignAddress, unsinged int addressLength)
- socket은 socket()에 의해 생성된 소켓
- foreignAddress는 소켓 API가 총괄적이기 때문에 sockaddr 포인터로 선언하는데 여기서는 항상 서버의 인터넷 주소 및 포트번호를 포함하는 sockaddr_in을 가리키는 포인터
- addressLength는 주소 구조체 길이 고정적 sizeof(struct sockaddr_in)
- 성공하면 그 소켓으로의 신뢰성 있는 채널이 존재한다는 의미
send()
int send(int socket, const void * msg, unsigned int msgLength, int flags)
- socket은 연결된 소켓의 식별자 이 소켓을 통해 데이터를 보내거나 받는다.
- msg는 보낼 메시지
- msgLength는 메시지의 길이로서 바이트 단위
- flags는 소켓 호출의 디폴트 동작을 변경시키는 방법을 제공
- sned()는 디폴트로 모든 데이터를 다 보낼떄까지 블록된다.
그런데 이 디폴트 동작을 바꿀수 있다.
recv()
int recv(int socket, void * rcvBuffer, unsigned int bufferLength, int flags)
- socket은 연결된 소켓의 식별자
- rcvBuffer는 받은 데이터를 저장하는 버퍼 문자배열과 같은 메모리상의 한영역 가리킨다.
- bufferLength 버퍼의 길이이고 또한 한꺼번에 받을 수 있는 최대 바이트 수
- flags는 send()함수의 flag와 같다.