一、udp_client、udp_connect、udp_server函数
int udp_conncet(const char *hostname, const char *service);
int udp_server(const char *hostname, const char *service, socklen_t *lenptr);
1. udp_client创建 未连接UDP套接字,返回 三项数据。① 套接字描述符;② saptr:指向某个由udp_client动态分配的套接字地址结构的一个指针的地址,该结构用于存放目的IP地址和端口,稍后用于调用sendto。③ lenptr:第二个套接字地址结构的大小存放再lenptr指针指向的变量中,且该参数不能为空指针。
2. udp_conncet用于创建 已连接UDP套接字,返回 一项数据(已连接套接字描述符)。因为有了已连接UDP套接字后,udp_client必须的结尾两个参数就不再需要了,调用者可改用write代替sendto,因此本函数不必返回一个套接字地址结构及其长度。本函数几乎等同于tcp_connect,差别之一是UDP套接字上的connect调用不再发送任何东西到对端。
3. udp_server创建 未连接UDP套接字,返回 两项数据(未连接套接字描述符和lenptr(指向套接字地址结构大小的指针))。该函数的参数和tcp_listen一样,只是该函数源码没有调用listen,除此之外,几乎等同于tcp_listen。注意:该函数service参数必须。
UDP用于访问getaddrinfo的比较简单的接口函数主要为udp_client、udp_connect和udp_server函数,这三个函数定义于《Unix网络编程 卷1:套接字联网API》(简称UNP)的头文件unp.h。udp_client函数用于创建未连接UDP套接字,udp_connect函数用于已连接UDP套接字,udp_server函数为用于简化访问getaddrinfo的最后一个UDP接口函数。这三个函数的原型为:
--------------------------------------------------------------------------------------------------------------------------------------------
#include "unp.h"
int udp_client(const char *hostname, const char *service, struct sockaddr **saptr, socklen_t *lenptr);int udp_conncet(const char *hostname, const char *service);
int udp_server(const char *hostname, const char *service, socklen_t *lenptr);
返回:若成功则返回“未/已/未”连接套接字描述符,若出错则不返回
------------------------------------------------------------------------------------------------------------------------------------------
参数解析:1. udp_client创建 未连接UDP套接字,返回 三项数据。① 套接字描述符;② saptr:指向某个由udp_client动态分配的套接字地址结构的一个指针的地址,该结构用于存放目的IP地址和端口,稍后用于调用sendto。③ lenptr:第二个套接字地址结构的大小存放再lenptr指针指向的变量中,且该参数不能为空指针。
2. udp_conncet用于创建 已连接UDP套接字,返回 一项数据(已连接套接字描述符)。因为有了已连接UDP套接字后,udp_client必须的结尾两个参数就不再需要了,调用者可改用write代替sendto,因此本函数不必返回一个套接字地址结构及其长度。本函数几乎等同于tcp_connect,差别之一是UDP套接字上的connect调用不再发送任何东西到对端。
3. udp_server创建 未连接UDP套接字,返回 两项数据(未连接套接字描述符和lenptr(指向套接字地址结构大小的指针))。该函数的参数和tcp_listen一样,只是该函数源码没有调用listen,除此之外,几乎等同于tcp_listen。注意:该函数service参数必须。
二、udp_client、udp_connect、udp_server函数源码
#include "unp.h"
int udp_client(const char *host, const char *serv, SA **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)
err_quit("udp_client 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)
break; /* success */
} while ( (res = res->ai_next) != NULL);
if (res == NULL) /* errno set from final socket() */
err_sys("udp_client error for %s, %s", host, serv);
*saptr = Malloc(res->ai_addrlen);
memcpy(*saptr, res->ai_addr, res->ai_addrlen);
*lenp = res->ai_addrlen;
freeaddrinfo(ressave);
return(sockfd);
}
int udp_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_DGRAM;
if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0)
err_quit("udp_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("udp_connect error for %s, %s", host, serv);
freeaddrinfo(ressave);
return(sockfd);
}
int udp_server(const char *host, const char *serv, socklen_t *addrlenp)
{
int sockfd, n;
struct addrinfo hints, *res, *ressave;
bzero(&hints, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0)
err_quit("udp_server 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; /* error - try next one */
if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0)
break; /* success */
Close(sockfd); /* bind error - close and try next one */
} while ( (res = res->ai_next) != NULL);
if (res == NULL) /* errno from final socket() or bind() */
err_sys("udp_server error for %s, %s", host, serv);
if (addrlenp)
*addrlenp = res->ai_addrlen; /* return size of protocol address */
freeaddrinfo(ressave);
return(sockfd);
}
三、协议无关的UDP时间获取客户程序(见UNP图11-16)——使用udp_client函数
#include <unistd.h>
#include <sys/types.h> /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h> /* inet(3) functions */
#include <sys/select.h> /* select function*/
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define MAXLINE 4098
int udp_client(const char *hostname, const char *service, struct sockaddr **saptr, socklen_t *lenptr);
int main(int argc, char **argv)
{
int sockfd, nrecv;
struct sockaddr *sa;
socklen_t salen;
char dst[MAXLINE];
char recvBuf[MAXLINE + 1];
if(argc != 3)
{
perror("usage: <hosename/IPaddress> <service/port#>");
}
sockfd = udp_client(argv[1], argv[2],(void **) &sa, &salen);
printf("Sending to %s\n", inet_ntop(AF_INET, sa, dst, MAXLINE));
sendto(sockfd, "", 1, 0, sa, salen);// send 1-byte datagram
nrecv = recvfrom(sockfd, recvBuf, MAXLINE, 0, NULL, NULL);// THE LAST TWO NULLS?
recvBuf[nrecv] = '\0'; // null terminate
fputs(recvBuf, stdout);
exit(0);
}
int udp_client(const char *hostname, const char *service, struct sockaddr **saptr, socklen_t *lenptr)
{
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(hostname, service, &hints, &res)) != 0)
// err_quit("udp_client error for %s, %s: %s",
printf("udp_client error for %s, %s: %s",
hostname, service, gai_strerror(n));
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() */
// err_sys("udp_client error for %s, %s", hostname, service);
printf("udp_client error for %s, %s", hostname, service);
*saptr = malloc(res->ai_addrlen);
memcpy(*saptr, res->ai_addr, res->ai_addrlen);
*lenptr = res->ai_addrlen;
freeaddrinfo(ressave);
return(sockfd);
}
编译及结果如下: