Unix Network Programming Episode 84

复制代码
#include "unp.h"
#include <time.h>

int main(int argc, char **argv)
{
    int sockfd;
    ssize_t n;
    char buff[MAXLINE];
    time_t ticks;
    socklen_t len;
    struct sockaddr_storage clientaddr;

    if(argc==2)
        sockfd=Udp_server(NULL, argv[1],NULL);
    else if(argc==3)
        sockfd=Udp_server(argv[1], argv[2],NULL);
    else
        err_quit("usage: daytimeudpserv [ <host> ] <service or port>");
    
    for(;;)
    {
        len=sizeof(clientaddr);
        n=Recvfrom(sockfd, buff, MAXLINE, 0, (SA *)&clientaddr, &len);
        printf("datagram from %s\n", Sock_ntop((SA *)&clientaddr, len));

        ticks=time(NULL);
        snprintf(buff, sizeoff(buff), "%0.24s\r\n", ctime(&ticks));
        Sendto(sockfd, buff, strlen(buff),0, (SA *)&clientaddr, len);
    }
}

Protocol-independent UDP daytime server

'getnameinfo' Function

This function is the complement of getaddrinfo: It takes a socket address and returns a character string describing the host and another character string describing the service. This function provides this information in a protocol-independent fashion; that is, the caller does not care what type of protocol address is contained in the socket address structure, as that detail is handled by the function.

复制代码
#include <netdb.h>
int getnameinfo (const struct sockaddr *sockaddr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) ;
Re-entrant Functions

The gethostbyname function from Section 11.3(See 8.9.3) presents an interesting problem that we have not yet examined in the text: It is not re-entrant. We will encounter this problem in general when we deal with threads in Chapter 26(See 9.15), but it is interesting to examine the problem now (without having to deal with the concept of threads) and to see how to fix it.

If we look at the name and address conversion functions presented in this chapter, along with the inet_XXX functions from Chapter 4(See 8.2), we note the following:

  • Historically, gethostbyname, gethostbyaddr, getservbyname, and get servbyport are not re-entrant because all return a pointer to a static structure.
    Some implementations that support threads (Solaris 2.x) provide re-entrant versions of these four functions with names ending with the_r suffix, which we will describe in the next section.
    Alternately, some implementations that support threads (HP-UX 10.30 and later) provide re-entrant versions of these functions using thread-specific data (Section 26.5(See 9.15.5)).
  • inet_pton and inet_ntop are always re-entrant.
  • Historically, inet_ntoa is not re-entrant, but some implementations that support threads provide a re-entrant version that uses thread-specific data.
  • getaddrinfo is re-entrant only if it calls re-entrant functions itself; that is, if it calls re-entrant versions of gethostbyname for the hostname and getservbyname for the service name. One reason that all the memory for the results is dynamically allocated is to allow it to be re-entrant.
  • getnameinfo is re-entrant only if it calls re-entrant functions itself; that is, if it calls re-entrant versions of gethostbyaddr to obtain the hostname and getservbyport to obtain the service name. Notice that both result strings (for the hostname and the service name) are allocated by the caller to allow this reentrancy.

A similar problem occurs with the variable errno. Historically, there has been a single copy of this integer variable per process. If a process makes a system call that returns an error, an integer error code is stored in this variable. For example, when the function named close in the standard C library is called, it might execute something like the following pseudocode:

  • Put the argument to the system call (an integer descriptor) into a register
  • Put a value in another register indicating the close system call is being called
  • Invoke the system call (switch to the kernel with a special instruction)
  • Test the value of a register to see if an error occurred
  • If no error, return (0)
  • Store the value of some other register into errno
  • return (-1)
'gethostbyname_r' and 'gethostbyaddr_r' Functions

There are two ways to make a nonre-entrant function such as gethostbyname re-entrant.

1.Instead of filling in and returning a static structure, the caller allocates the structure and the re-entrant function fills in the caller's structure.

2.The re-entrant function calls malloc and dynamically allocates the memory. This is the technique used by getaddrinfo.

复制代码
#include <netdb.h>
struct hostent *gethostbyname_r (const char *hostname, struct hostent *result, char *buf, int buflen, int *h_errnop) ;
struct hostent *gethostbyaddr_r (const char *addr, int len, int type, struct hostent *result, char *buf, int buflen, int *h_errnop) ;
Obsolete IPv6 Address Lookup Functions

While IPv6 was being developed, the API to request the lookup of an IPv6 address went through several iterations. The resulting API was complicated and not sufficiently flexible, so it was deprecated in RFC 2553 [Gilligan et al. 1999].

The gethostbyname2 Function

The gethostbyname2 function adds an address family argument to gethostbyname.

复制代码
#include <sys/socket.h>
#include <netdb.h>
struct hostent *gethostbyname2 (const char *name, int af) ;
The getipnodebyname Function

RFC 2553 [Gilligan et al. 1999] deprecated RES_USE_INET6 and gethostbyname2 because of the global nature of the RES_USE_INET6 flag and the wish to provide more control over the returned information. It introduced the getipnodebyname function to solve some of these problems.

复制代码
#include <sys/socket.h>
#include <netdb.h>
struct hostent *getipnodebyname (const char *name, int af, int flags, int *error_num) ;

This function returns a pointer to the same hostent structure that we described with gethostbyname. The af and flags arguments map directly to getaddrinfo's hints.ai_family and hints.ai_flags arguments. For thread safety, the return value is dynamically allocated, so it must be freed with the freehostent function.

复制代码
#include <netdb.h>
void freehostent (struct hostent *ptr) ;
Other Networking Information

Our focus in this chapter has been on hostnames and IP addresses and service names and their port numbers. But looking at the bigger picture, there are four types of information (related to networking) that an application might want to look up: hosts, networks, protocols, and services. Most lookups are for hosts (gethostbyname and gethòstbyaddr), with a smaller number for services (getservbyname and getservbyaddr), and an even smaller number for networks and protocols.

All four types of information can be stored in a file and three functions are defined for each of the four types:

1.A getXXXent function that reads the next entry in the file, opening the file if necessary.

2.A setXXXent function that opens (if not already open) and rewinds the file.

3.An endXXXent function that closes the file.

相关推荐
invicinble8 小时前
对linux形成认识
linux·运维·服务器
技术路上的探险家8 小时前
8 卡 V100 服务器:基于 vLLM 的 Qwen 大模型高效部署实战
运维·服务器·语言模型
半桔9 小时前
【IO多路转接】高并发服务器实战:Reactor 框架与 Epoll 机制的封装与设计逻辑
linux·运维·服务器·c++·io
绵绵细雨中的乡音9 小时前
深入理解 ET 与 LT 模式及其在 Reactor 模型中的应用
服务器·网络·php
HABuo9 小时前
【linux文件系统】磁盘结构&文件系统详谈
linux·运维·服务器·c语言·c++·ubuntu·centos
Howrun77710 小时前
关于Linux服务器的协作问题
linux·运维·服务器
yunfuuwqi11 小时前
OpenClaw✅真·喂饭级教程:2026年OpenClaw(原Moltbot)一键部署+接入飞书最佳实践
运维·服务器·网络·人工智能·飞书·京东云
代码游侠12 小时前
C语言核心概念复习——网络协议与TCP/IP
linux·运维·服务器·网络·算法
你真是饿了12 小时前
6.库制作与原理
linux·服务器
Zach_yuan13 小时前
深入浅出 JSONCpp
linux·服务器·网络·c++