Unix网络编程 卷1 第11章:名字与地址转换(udp_client_connect_connect)

一、udp_client、udp_connect、udp_server函数

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);
}
编译及结果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值