名字和数值地址间的转换函数(IPV4):
gethostbyname
gethostbyaddr
服务名字和端口号之间转换:
getservbyname
getservbyport
协议无关函数:
getaddrinfo : 主机名字和IP之间的转换
getnameinfo : 服务名字和端口号
协议无关的tcp创建函数:
使用getaddrinfo, 有助于编写协议无关的函数,不过需要填写 一个 addrinfo 来告诉getaddrinfo,我们的需求时什么。
使用getaddrinfo编写一些常用的函数:
连接一个TCP服务器: 返回“已经连接套接字”
static SOCKET create_and_connec(const char *address, const char *port) { struct addrinfo hints; struct addrinfo *result, *rp; int s; SOCKET sfd; memset(&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ hints.ai_flags = AI_PASSIVE; /* All interfaces */ s = getaddrinfo(address, port, &hints, &result); if (s != 0) { CLog::Error("getaddrinfo: %s", gai_strerror(s)); return INVALID_SOCKET; } for (rp = result; rp != NULL; rp = rp->ai_next) { sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sfd == INVALID_SOCKET) continue; s = connect(sfd, rp->ai_addr, rp->ai_addrlen); if (s == 0) { /* We managed to bind successfully! */ printf_address(sfd, rp->ai_addr, rp->ai_addrlen, "Connect to"); int flags = 1; if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flags, sizeof(int)) < 0) { CLog::Error("setsockopt TCP_NODELAY error, errno %d", errno); } break; } closesocket(sfd); } if (rp == NULL) { CLog::Error("Could not bind\n"); return INVALID_SOCKET; } freeaddrinfo(result); return sfd; }
创建一个TCP服务器,返回监听套接字
int tcp_listen(const char *host, const char *serv, socklen_t *addrlenp) { int listenfd, n; const int on = 1; struct addrinfo hints, *res, *ressave; bzero(&hints, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { fprintf(stderr, "tcp_listen error for %s, %s: %s", host, serv, gai_strerror(n)); exit(1); } ressave = res; do { listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (listenfd < 0) continue; /* error, try next one */ setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) break; /* success */ close(listenfd); /* bind error, close and try next one */ } while ( (res = res->ai_next) != NULL); if (res == NULL){ /* errno from final socket() or bind() */ fprintf(stderr, "tcp_listen error for %s, %s", host, serv); exit(1); } listen(listenfd, LISTENQ); if (addrlenp) *addrlenp = res->ai_addrlen; /* return size of protocol address */ freeaddrinfo(ressave); return(listenfd); }
int tcp_connect(const char *host, const char *serv) { int sockfd, n; struct addrinfo hints, *res, *ressave; bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) err_quit("tcp_connect error for %s, %s: %s", host, serv, gai_strerror(n)); ressave = res; do { sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) continue; /* ignore this one */ if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0) break; /* success */ close(sockfd); /* ignore this one */ } while ( (res = res->ai_next) != NULL); if (res == NULL) /* errno set from final connect() */ err_sys("tcp_connect error for %s, %s", host, serv); freeaddrinfo(ressave); return(sockfd); }
int tcp_listen(const char *host, const char *serv, socklen_t *addrlenp) { int listenfd, n; const int on = 1; struct addrinfo hints, *res, *ressave; bzero(&hints, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) err_quit("tcp_listen error for %s, %s: %s", host, serv, gai_strerror(n)); ressave = res; do { listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (listenfd < 0) continue; /* error, try next one */ Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) break; /* success */ Close(listenfd); /* bind error, close and try next one */ } while ( (res = res->ai_next) != NULL); if (res == NULL) /* errno from final socket() or bind() */ err_sys("tcp_listen error for %s, %s", host, serv); Listen(listenfd, LISTENQ); if (addrlenp) *addrlenp = res->ai_addrlen; /* return size of protocol address */ freeaddrinfo(ressave); return(listenfd); }
实践代码:https://github.com/huntinux/unpvol1/tree/master/11chp