티스토리 뷰
☞ sendto, recvfrom
<sys/socket.h>
ssize_t sendto(int socket, const void *buffer, size_t size, int flags, struct sockaddr *addr, socklen_t length);
ssize_t recvfrom(int socket, void *buffer, size_t size, int flags, struct sockaddr *addr, socklen_t *lenptr);
데이터 그램 소켓은 비연결 기반의 메시지 전달로 내용과 순서에 신뢰성을 확보 할 수 없습니다.
각 전송 단위마다 수신 주소를 지정합니다. 연결 기반 소켓에 사용하는 listen(), accept(), connect()등은 데이터 그램 소켓에 적용되지 않지만,
connect()를 데이터그램(SOCK_DGRAM)에 사용하는 경우는 연결 기반 소켓으로 동작하는 것은 아니고 기본 목적지로 적용됩니다. 기본 목적지가 있는 데이터 그램 소켓에는 write(), send()를 사용할 수 있습니다.
sendto()는 *addr과 *lenptr 지정한 호스트에 메시지를 전송합니다. flags는 send()와 같은 방식으로 적용합니다.
성공하면 전송된 바이트수를 리턴하고 실패하면 -1을 리턴하지만 메시지가 실제로 지정한 호스트에 전달되었는지는 확인할 수 없습니다.
recvfrom()에서 인수 *addr를 NULL로 넘기거나 recv()를 사용하면 어디에서 보낸 메시지인지 무시하고 메시지만을 읽습니다.
*addr과 *lenptr를 전달하면 메시지를 전송한 호스트의 정보를 함께 저장합니다. size는 최대 메시지의 길이로 전달된 메시지가 이 값 보다 길면 size까지만 읽히고 나머지는 버려집니다.
최대 메시지 길이를 감안하여 데이터 그램 읽기를 수행해야 합니다.
☞ 예제1
static void hb_cluster_send_heartbeat_internal (struct sockaddr_in *saddr, socklen_t saddr_len, char *dest_host_name, bool is_req) { HBP_HEADER *hbp_header; char buffer[HB_BUFFER_SZ], *p; size_t hb_len; int send_len; memset ((void *) buffer, 0, sizeof (buffer)); hbp_header = (HBP_HEADER *) (&buffer[0]); hb_set_net_header (hbp_header, HBP_CLUSTER_HEARTBEAT, is_req, OR_INT_SIZE, 0, dest_host_name); p = (char *) (hbp_header + 1); p = or_pack_int (p, hb_Cluster->state); hb_len = sizeof (HBP_HEADER) + OR_INT_SIZE; send_len = sendto (hb_Cluster->sfd, (void *) &buffer[0], hb_len, 0, (struct sockaddr *) saddr, saddr_len); if (send_len <= 0) { MASTER_ER_LOG_DEBUG (ARG_FILE_LINE, "sendto failed. \n"); } return; } static void *hb_thread_cluster_reader (void *arg) { int error; SOCKET sfd; char buffer[HB_BUFFER_SZ + MAX_ALIGNMENT], *aligned_buffer; int len; struct pollfd po[1] = { {0, 0, 0} }; struct sockaddr_in from; socklen_t from_len; aligned_buffer = PTR_ALIGN (buffer, MAX_ALIGNMENT); sfd = hb_Cluster->sfd; while (hb_Cluster->shutdown == false) { po[0].fd = sfd; po[0].events = POLLIN; error = poll (po, 1, 1); if (error <= 0) { continue; } if ((po[0].revents & POLLIN) && sfd == hb_Cluster->sfd) { from_len = sizeof (from); len = recvfrom (sfd, (void *) aligned_buffer, HB_BUFFER_SZ, 0, (struct sockaddr *) &from, &from_len); if (len > 0) { hb_cluster_receive_heartbeat (aligned_buffer, len, &from, from_len); } } } return NULL; }
위의 예제 코드는 큐브리드 DBMS에서 클러스터링 기능을 구현하는데 적용한 데이터그램 사용 예제입니다.
'C | C++' 카테고리의 다른 글
시스템 로그 (0) | 2018.06.29 |
---|---|
터미널 IO (0) | 2018.06.29 |
연결 기반으로 소켓 사용하기 (0) | 2018.06.17 |
소켓 생성 및 닫기 (0) | 2018.06.17 |
소켓 바이트 오더 변환 (0) | 2018.06.17 |