名字和数值地址间的转换函数(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);
}
连接到一个TCP服务器,(功能同create_and_connec)
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);
}
创建一个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)
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