IRC
소켓
-
프로세스가 네트워크 세계로 데이터를 내보내거나 데이터를 받기 위한 실제적인 창구 역할.
-
프로세스가 데이터를 보내거나 받기 위해 반드시 소켓을 열어 소켓에 데이터를 쓰고읽어야한다.
-
소켓은 프로토콜, IP, 포트 넘버로 정의된다.
- 프로토콜: 어떤 시스템이 다른 시스템과 통신을 원활하게 수용하도록 해주는 통신 규약
- IP: 전 세계 컴퓨터에 부여된 고유 식별 주소
- 포트: 네트워크 상에서 통신하기 위해서 호스트 내부적으로 프로세스가 할당받아야 하는 고유한 숫자. 한 호스트 내에서 네트워크 통신을 하고 있는 프로세스를 식별하기 위해 사용되는 값. 같은 호스트 내에서 서로 다른 프로세스는 같은 포트 넘버를 가질 수 없다. (= 같은 컴퓨터 내에서 프로그램을 식별하는 번호).
=> 소켓 : 떨어져 있는 두 호스트를 연결해주는 도구, 인터페이스 역할, 데이터를 주고 받을 수 있는 구조체로 소켓을 통해 데이터 통로가 만들어진다.
역할에 따라 서버 소켓, 클라이언트 소켓으로 구분

포트
- 추상적이고 소프트웨어적인 포트 -> 네트워크 상에서 이 컴퓨터와 다른 컴퓨터와 서로 연결되는 부분 혹은 통로라고 생각.
포트 바인딩
- 메세지를 송수신 하는 위치와 방법을 결정하는 구성 정보.
- 메세지 수신 포트 바인딩 유형
- 메세지 송신 포트 바인딩 유형
sockaddr
- 선택한 프로토콜에 따라 달라짐.
- 구조체의 sockaddr 구조체 및 sockaddr은 _ IPv4와 함께 사용.
struct sockaddr {
ushort sa_family;
char sa_data[14];
};
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
htons()
- 데이터를 네트워크 바이트 순서로 변환
- 데이터는 바이트 단위로 저장되지만 저장되는 방식에 있어서 CPU마다 차이가 발생하게 된다. ex) 4바이트 크기의 int자료를 저장한다고 했을 때 어떤 CPU는 가장 낮은 바이트부터 저장을 하는가 하면, 어떤 CPU는 가장 높은 바이트 부터 데이터를 저장하기도 한다. 전자를 Little Endian방식, 후자를 Big Endian방식 이라고 한다.
- 이런 이유로 서로 다른 데이터 저장 방식을 사용하는 시스템끼리 통신을 하게 될경우 전혀 원하지 않는 값들을 서로 주고 받는 경우가 발생할 수 있다. 한쪽에서는 12345를 보냈는데, 다른 한쪽에서는 엉뚱하게 365779719로 받아 들이는 문제들이 발생한다.
- 이런 문제를 해결하기 위해서 데이터 통신을 할때는 명시적으로 네트워크 byte order을 따르도록 데이터의 byte order를 변경한다. 네트워크 byte order는 Big Endiasn을 따른다.
- 원격 호스트와 데이터 통신을 하길 원한다면 보낼 때 네트워크 byte order로, 받았을 때는 호스트 byteorder로 변경한다.
- htons()함수는 short intger(일반적으로 2byte)데이터를 네트워크 byte order로 변경한다.
- Retrun: 네트워크 byte order된 2바이트 값을 넘겨준다.
bind()
- bind(hListen, (SOCKADDR*)&tListenAddr, sizeof(tListenAddr));
- bind(소켓, 소켓 구성요소 구조체의 주소, 그 구조체의 크기);
- 소켓에 주소 정보를 연결 = Listen소켓의 역할은 접속승인만, 위에서 설정한 주소 정보를 bind함수를 이용해 소켓에 묶어준다.
Listen()
- 연결을 수신하는 상태로 소켓의 상태를 변경. = 소켓을 접속 대기 상태로 만들어준다.
kqueue()
- kqueue() 시스템 호출은 kqueue 파일 서술자를 할당합니다. 이 파일 서술자는 필터에 따라 사용자에게 커널 이벤트(kevent) 발생이나 조건과 일치하는 경우(condition holds)를 알아내는 메서드를 제공합니다.
kevent61_s 구조체
struct kevent64_s
{
uint64_t ident;
int16_t filter;
uint16_t flags;
uint32_t fflags;
int64_t data;
uint64_t udata;
uint64_t ext[2];
};
- ident 이벤트의 source를 식별하는 데 사용되는 값입니다. 정확한 해석은 filter 의해 결정되지만, 주로 파일 디스크립터를 통해 결정됩니다.
- filter 이 이벤트를 처리하는 데 사용되는 커널 필터를 식별합니다. 사전 정의된 시스템 필터는 아래에 설명되어 있습니다.
3 .flags 이벤트에서 수행될 작업입니다.
- fflags 필터에 따른 플래그입니다.
- data 필터에 따른 데이터입니다.
- udata 커널을 통해 전달된 불투명한 사용자 정의 값은 변경되지 않습니다. 선택적으로 kevent 시스템의 고유한 결정의 일부가 될 수 있습니다.
+7. ext[2] 이 필드는 이벤트 필터에 대한 확장을 저장합니다. 확장 유형은 사용 중인 필터에 따라 다릅니다.
kevent64()
- kevent(), kevent64() 및 kevent_qos() 시스템 호출은 eventlist에 있는 이벤트 수를 최대 nevents에 의해 제공된 값까지 반환합니다. changelist의 요소를 처리하는 동안 오류가 발생하고 eventlist에 충분한 공간이 있는 경우 이벤트는 플래그에 설정된 EV_ERROR 및 데이터의 시스템 오류와 함께 이벤트 목록에 배치됩니다. 그렇지 않으면 -1이 반환되고 errno가 오류 조건을 나타내도록 설정됩니다. timeout이 만료되면 kevent(), kevent64() 및 kevent_qos()가 0을 반환합니다.
EV_SET64()
- EV_SET() 매크로는 kevent 구조체를 쉽게 초기화하기 위해 제공됩니다. 마찬가지로 EV_SET64()는 kevent64_s 구조체를 초기화하고 EV_SET_QOS()는 kevent_qos_s 구조체를 초기화합니다.
recv()
int send(int socket, const void *msg, size_t len, int flags);
int recv(int socket, void *buf, size_t len, int flags);
- int socket: 통신의 주체가 되는 소켓 디스크립터
- send : 정보를 받을 소켓 디스크립터 주소
- recv : 정보를 보내는 소켓 디스크립터 주소
- const void *msg : 상대에게 보낼 자료의 포인터
- void *buf : 받은 메세지를 저장할 버퍼 포인터
- size_t len : 전송되는 메세지의 크기 (byte 단위)
- int flag : 플래그 (옵션)

return: 실제 전송(수신)한 바이트 수, 실패 시 -1
accept()
-
SOCKET hClient = accept(hListen, (SOCKADDR*)&tClntAddr, &iClntSize);
-
accept(소켓, 소켓 구성요소 주소체의 주소, 그 구조체의 크기를 담고있는 변수의 주소);
-
accept 함수를 이용하여 접속 요청을 수락. 동기화된 방식으로 동작(요청을 마무리 하기 전까지 계속 대기상태에 놓이게 되는 것 = 요청이 들어오기 전까지 이 함수를 빠져나오지 않는다.)
-
접속 요청을 승인하면 연결된 소켓이 만들어져서 리턴된다. 이렇게 만들어진 소켓을 이용해서 통신.
-
첫번째 인자로는 소켓을 넣어준다.
-
두번째 인자로는 accept 할 클라이언트측 주소정보 구조체의 주소가 들어간다.(SOCKADDR* 타입 형변환)
-
세번째 인자로는 두번째 인자로 넣은 구조체의 크기를 저장해둔 변수의 주소가 들어간다.
출처
링크텍스트
링크텍스트