함수 설명
- create_ssdp_receiver - socket 생성/bind/multicast join
- release_ssdp_receiver - 소켓 구조체 메모리 해제
- pending_ssdp_receiver - multiplex wait (select 함수)
- receive_ssdp_packet - packet 수신 및 출력
- main - 샘플 프로그램
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <net/if.h>
#define SSDP_HOST "239.255.255.250"
#define SSDP_PORT 1900
#define SSDP_PORTSTR "1900"
typedef struct _ssdp_receiver_t
{
int sock;
fd_set read_fds;
} ssdp_receiver_t;
static ssdp_receiver_t * create_ssdp_receiver(void)
{
int on = 1;
struct addrinfo hints, * res;
struct sockaddr_in addr;
struct ip_mreq mreq;
ssdp_receiver_t * receiver = (ssdp_receiver_t*)malloc(sizeof(ssdp_receiver_t));
memset(receiver, 0, sizeof(ssdp_receiver_t));
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
assert(getaddrinfo(NULL, SSDP_PORTSTR, &hints, &res) == 0);
receiver->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
assert(receiver->sock >= 0);
assert(setsockopt(receiver->sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == 0);
assert(bind(receiver->sock, res->ai_addr, res->ai_addrlen) == 0);
freeaddrinfo(res);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST;
assert(getaddrinfo(SSDP_HOST, NULL, &hints, &res) == 0);
memcpy(&mreq.imr_multiaddr, &(((struct sockaddr_in*)res->ai_addr)->sin_addr), sizeof(mreq.imr_multiaddr));
freeaddrinfo(res);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
assert(setsockopt(receiver->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == 0);
FD_ZERO(&receiver->read_fds);
FD_SET(receiver->sock, &(receiver->read_fds));
return receiver;
}
static void release_ssdp_receiver(ssdp_receiver_t * receiver) {
/*
* IP_DROP_MEMBERSHIP is not necessary
* ----
* [http://www.tldp.org/HOWTO/Multicast-HOWTO-6.html]
*/
close(receiver->sock);
free(receiver);
}
static int pending_ssdp_receiver(ssdp_receiver_t * receiver, unsigned long wait_milli) {
fd_set fds = receiver->read_fds;
struct timeval timeout;
timeout.tv_sec = wait_milli / 1000;
timeout.tv_usec = (wait_milli % 1000) * 1000;
return select(receiver->sock + 1, &fds, NULL, NULL, &timeout);
}
static void receive_ssdp_packet(ssdp_receiver_t * receiver) {
char buffer[4096] = {0,};
struct sockaddr_in addr = {0,};
socklen_t addr_len = sizeof(addr);
int len = recvfrom(receiver->sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &addr_len);
assert(len > 0);
printf("[RECV]\n");
printf("%s", buffer);
}
int main(int argc, char *argv[])
{
ssdp_receiver_t * receiver = NULL;
receiver = create_ssdp_receiver();
int count = 0;
while (1)
{
if (pending_ssdp_receiver(receiver, 100) > 0)
{
printf("count: %d\n", count++);
receive_ssdp_packet(receiver);
}
}
return 0;
}
댓글 없음:
댓글 쓰기