通常说函数返回某个错误值,实际上是函数返回值为-1,而全局变量errno被置为指定的常值(即称函数返回这个错误值)。

exit终止进程,Unix在一个进程终止时总是关闭该进程所有打开的描述符

TCP三次握手完毕,accept返回其返回值是一个称为已连接描述符(connected descriptor)的新描述符。调用close关闭与客户的连接。

套接字API

TCP状态转移图,11种状态。

MSS,maximum segment size,最大分节大小。通常客户端主动打开时发送SYN的同时会发送MSS,服务端应答(SYN、ACK、MSS)时同样也发送一个MSS,不同方向上MSS可以不同

 

SCTP多宿特性,单个SCTP端点能支持多个IP地址。

SCTP的四路握手。验证标记、状态cookie。

 

IPv4数据报最大长度65535,包括IP首部,因为总长度字段是16位;IPv6数据报最大长度65575,包括40字节IPv6首部因为净长度字段是16位。

IPv4首部20字节(固定长度),另外还有最多40字节可选部分

 

套接字地址结构在内核和进程间传递,从进程传到内核,从内核传到进程,不是非常理解,应该就是参数传递进去和被写回吧?另外有一个值-结果参数以前很少碰到。

 每个文件套接字都有一个引用计数,引用计数在文件表项中维护。

存放在硬盘上的可执行程序文件能被Unix执行的唯一方法是:由一个现有进程调用六个exec函数中的一个。(理解)

六个exec函数区别在于:待执行程序由文件名还是路径名指定参数是一一列出还是指针数组把调用进程环境传递给新程序还是指定新环境

子进程调用exec时,子进程内存映像被替换成新程序文件,只有文件描述符(在socket中是已连接套接字描述符)跨exec继续保持开放

 

一个简单echo客户/服务器程序涉及到的一些细节(非常重要):

僵死子进程,通过捕获SIGCHLD信号加以处理;

信号处理函数必须调用waitpid而不是wait,因为unix信号是不排队的,当有多个子进程时wait函数只能处理第一个,后面的将变成僵死进程;

另一个问题是服务器进程终止时,客户进程没被告知,因为客户进程阻塞于等待用户输入而未接收到通知,这需要select或poll函数来处理,它们等待多个描述符中的任何一个就绪而不是阻塞于某个描述符。

select函数中间的三个参数(读、写、异常描述符集)都是值—结果参数,返回时,未就绪描述符对应的被置0,其他是1,重新调用时,将所关心位重置1

close函数有两个限制,shutdown函数可以克服,它关闭一半tcp连接(可参数选读或者写)。

pselect间参数结构不同另一个不同点是多了一个指向信号掩码的指针,从而运行程序先禁止提交某些信号。

 

拒绝服务(denial of service,DoS)型攻击。

 

UDP也可以使用connect函数,成为已连接UDP套接字,然后可以使用write和read函数读写,而不是sento和recvfrom。

 

DNS中的条目称为资源记录(resource record,RR)。常见RR类型有:A、AAAA、PTR、MX、CNAME。

 

gethostbyname和gehostbyaddr的返回值均为一个hostent(host entry缩写)结构:

struct    hostent {
    const char    *h_name;    // 主机的正式名称。 
    char    **h_aliases;    //  空字节-地址的预备名称的指针。
    short    h_addrtype;    // 地址类型; 通常是AF_INET。 
    short    h_length;    // 地址的比特长度
    char    **h_addr_list;    //  主机网络地址指针(只有IPV4
   #define    h_addr    h_addr_list[0]    // h_addr 为 h_addr_list中的第一地址。 
};

gethostbyname只能返回IPV4地址,而getaddrinfo能够同时处理IPV4和IPV6地址。

gethostbyname和gehostbyaddr用于主机名和地址的映射,而getservbyname和getservbyport则用于服务与端口之间的映射。

getaddrinfo能处理名字到地址、服务到端口的转换(由参数中列表中第一个为主机名,第二个为服务名可看出):

int getaddrinfo( const char *hostname, 
    const char *service, 
    const struct addrinfo *hints, 
    struct addrinfo **result );//返回结果保存到这里

其中,保存返回结果的struct addrinfo结构体详细信息如下:

表头文件: #include<netdb.h>

struct addrinfo
{ 
int ai_flags; 
int ai_family; //AF_INET,AF_INET6,UNIX etc
int ai_socktype; //STREAM,DATAGRAM,RAW
int ai_protocol; //IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc
size_t ai_addrlen;//length of ai_addr
char* ai_canonname; //full hostname 
struct sockaddr* ai_addr; //addr of host
struct addrinfo* ai_next;
}

value of ai_falgs:
AI_PASSIVE: Socket address is intended for `bind'.
AI_CANONNAME:Request for canonical name.
AI_NUMERICHOST: Don't use name resolution.
AI_V4MAPPED: IPv4 mapped addresses are acceptable. 
AI_ALL: Return IPv4 mapped and IPv6 addresses. 
AI_ADDRCONFIG:Use configuration of this host to choose

定义函数: 
int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints,
struct addrinfo **result );

函数说明:
      getaddrinfo函数能够处理名字到地址以及服务到端口这两种转换,返回的是一个sockaddr 结构的链而 不是一个地址清单。它具有协议无关性。
      hostname:一个主机名或者地址串(IPv4的点分十进制串或者IPv6的16进制串)
      service:一个服务名或者10进制端口号数串。
       hints:可以是一个空指针,也可以是一个指向某个addrinfo结构的指针,调用者在这个结构中填入关于期望返回的信息类型的暗示。举例来说:如果指定的服务既支持TCP也支持UDP,那么调用者可以把hints结构中的ai_socktype成员设置成SOCK_DGRAM使得返回的仅仅是适用于数据报套接口的信息。返回0: 成功,返回非0: 出错。

定义函数:const char *gai_strerror( int error );
函数说明:
      该函数以getaddrinfo返回的非0错误值的名字和含义为他的唯一参数,返回一个指向对应的出错信息串的指针。

定义函数: void freeaddrinfo( struct addrinfo *ai );
函数说明:
       由getaddrinfo返回的所有存储空间都是动态获取的,这些存储空间必须通过调用freeaddrinfo返回给系统。
struct addrinfo结构体

相关文章:

  • 2021-06-20
  • 2021-07-06
  • 2021-09-09
  • 2021-11-13
  • 2021-05-14
  • 2021-12-25
  • 2021-05-05
  • 2021-11-28
猜你喜欢
  • 2021-12-30
  • 2021-04-03
  • 2021-08-26
  • 2022-01-17
  • 2021-11-12
  • 2021-12-26
  • 2021-12-07
  • 2021-12-02
相关资源
相似解决方案