📄 duobo.c
字号:
#include <sys/utsname.h>#include <sys/ioctl.h>#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>#include <net/if.h>#define MAXLINE 255#define MAXSOCKADDR 30void recv_all(int, socklen_t);void send_all(int, struct sockaddr *, socklen_t);int Udp_client(const char *, const char *, void **, socklen_t *);char *Sock_ntop(const struct sockaddr *, socklen_t );voidMcast_join(int, const struct sockaddr *, socklen_t ,const char *, u_int );voidMcast_set_loop(int , int );intSockfd_to_family(int sockfd);int main(int argc, char **argv){ int sendfd, recvfd; const int on = 1; socklen_t salen; struct sockaddr *sasend, *sarecv; if (argc != 3) { printf("usage: sendrecv <IP-multicast-address> <port#>"); exit(1); } sendfd = Udp_client(argv[1], argv[2], (void **) &sasend, &salen); recvfd = socket(sasend->sa_family, SOCK_DGRAM, 0); setsockopt(recvfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); sarecv = malloc(salen); memcpy(sarecv, sasend, salen); bind(recvfd, sarecv, salen); mcast_join(recvfd, sasend, salen, NULL, 0); mcast_set_loop(sendfd, 0); if (fork() == 0) recv_all(recvfd, salen); /* child -> receives */ send_all(sendfd, sasend, salen); /* parent -> sends */}voidrecv_all(int recvfd, socklen_t salen){ int n; char line[MAXLINE+1]; socklen_t len; struct sockaddr *safrom; safrom = malloc(salen); for ( ; ; ) { len = salen; n = recvfrom(recvfd, line, MAXLINE, 0, safrom, &len); line[n] = 0; /* null terminate */ printf("from %s: %s", Sock_ntop(safrom, len), line); }}voidsend_all(int sendfd, struct sockaddr *sadest, socklen_t salen){ static char line[MAXLINE]; /* hostname and process ID */ struct utsname myname; if (uname(&myname) < 0) { printf("uname error"); exit(0); } snprintf(line, sizeof(line), "%s, %d\n", myname.nodename, getpid()); for ( ; ; ) { sendto(sendfd, line, strlen(line), 0, sadest, salen); sleep(10); }}intUdp_client(const char *host, const char *serv, void **saptr, socklen_t *lenp){ int sockfd, n; struct addrinfo hints, *res, *ressave; bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { printf("udp_client error for %s, %s: %s", host, serv, gai_strerror(n)); exit(0); } ressave = res; do { sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd >= 0) break; /* success */ } while ( (res = res->ai_next) != NULL); if (res == NULL) /* errno set from final socket() */{ printf("udp_client error for %s, %s", host, serv); exit(0); } *saptr = malloc(res->ai_addrlen); memcpy(*saptr, res->ai_addr, res->ai_addrlen); *lenp = res->ai_addrlen; freeaddrinfo(ressave); return(sockfd);}char *sock_ntop(const struct sockaddr *sa, socklen_t salen){ char portstr[7]; static char str[128]; /* Unix domain is largest */ switch (sa->sa_family) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) return(NULL); if (ntohs(sin->sin_port) != 0) { snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port)); strcat(str, portstr); } return(str); }/* end sock_ntop */#ifdef IPV6 case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) return(NULL); if (ntohs(sin6->sin6_port) != 0) { snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port)); strcat(str, portstr); } return(str); }#endif default: snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen); return(str); } return (NULL);}char *Sock_ntop(const struct sockaddr *sa, socklen_t salen){ char *ptr; if ( (ptr = sock_ntop(sa, salen)) == NULL) { printf("sock_ntop error"); exit(0); } return(ptr);}intmcast_join(int sockfd, const struct sockaddr *sa, socklen_t salen, const char *ifname, u_int ifindex){ switch (sa->sa_family) { case AF_INET: { struct ip_mreq mreq; struct ifreq ifreq; memcpy(&mreq.imr_multiaddr, &((struct sockaddr_in *) sa)->sin_addr, sizeof(struct in_addr)); if (ifindex > 0) { if (if_indextoname(ifindex, ifreq.ifr_name) == NULL) { errno = ENXIO; /* i/f index not found */ return(-1); } goto doioctl; } else if (ifname != NULL) { strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);doioctl: if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0) return(-1); memcpy(&mreq.imr_interface, &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr)); } else mreq.imr_interface.s_addr = htonl(INADDR_ANY); return(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))); }/* end mcast_join1 *//* include mcast_join2 */#ifdef IPV6 case AF_INET6: { struct ipv6_mreq mreq6; memcpy(&mreq6.ipv6mr_multiaddr, &((struct sockaddr_in6 *) sa)->sin6_addr, sizeof(struct in6_addr)); if (ifindex > 0) mreq6.ipv6mr_interface = ifindex; else if (ifname != NULL) if ( (mreq6.ipv6mr_interface = if_nametoindex(ifname)) == 0) { errno = ENXIO; /* i/f name not found */ return(-1); } else mreq6.ipv6mr_interface = 0; return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6))); }#endif default: errno = EPROTONOSUPPORT; return(-1); }}/* end mcast_join2 */voidMcast_join(int sockfd, const struct sockaddr *sa, socklen_t salen, const char *ifname, u_int ifindex){ if (mcast_join(sockfd, sa, salen, ifname, ifindex) < 0) { printf("mcast_join error"); exit(0); }}intmcast_set_loop(int sockfd, int onoff){ switch (sockfd_to_family(sockfd)) { case AF_INET: { u_char flag; flag = onoff; return(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &flag, sizeof(flag))); }#ifdef IPV6 case AF_INET6: { u_int flag; flag = onoff; return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &flag, sizeof(flag))); }#endif default: errno = EPROTONOSUPPORT; return(-1); }}/* end mcast_set_loop */voidMcast_set_loop(int sockfd, int onoff){ if (mcast_set_loop(sockfd, onoff) < 0) { printf("mcast_set_loop error"); exit(0); }}intsockfd_to_family(int sockfd){ struct sockaddr sa; char data[MAXSOCKADDR]; socklen_t len; len = MAXSOCKADDR; if (getsockname(sockfd, (struct sockaddr *) data, &len) < 0) return(-1); return(sa.sa_family);}/* end sockfd_to_family */intSockfd_to_family(int sockfd){ int rc; if ( (rc = sockfd_to_family(sockfd)) < 0) { printf("sockfd_to_family error"); exit(0); } return(rc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -