unix网络编程读书笔记1复习过程.docx
《unix网络编程读书笔记1复习过程.docx》由会员分享,可在线阅读,更多相关《unix网络编程读书笔记1复习过程.docx(21页珍藏版)》请在冰豆网上搜索。
unix网络编程读书笔记1复习过程
Socket定义的结构体
#include
Structin_addr{
In_addr_ts_addr;32位PIv4地址网络字节序
}
Structsockaddr_in{
Uint8_tsin_len;//结构长度(16)不管它
Sa_family_tsin_family;//协议族AF_INET8位或16位无符号整数
In_port_tsin_port;//16位TCPUDP端口号
//网络字节序
Structin_addrsin_addr;//32位IPv4地址
//网络字节序
Charsin_zero[8];//unused
}
从进程到内核传递套接口地址结构4个套接口函数:
Bind
Connect
Sendto
Sendmsg//地址结构长度参数是一个结构成员
从内核到进程传递套接口地址结构的5个套接口函数:
Accept
Recvfrom
Recvmsg//地址结构长度参数是一个结构成员
Getpeername
Getsockname
//均在返回到进程之前设置sin_len成员
Posix只需要这个结构中的三个成员:
sin_familysin_addrsin_port
Int8_t带符号的8位整数·Uint8_t无符号8位整数·Int16_t带符号16位整数·Uint16_t无符号16位整数·Int32_t带符号32位整数·Uint32_t无符号32位整数
Sa_family_t套接口地址结构的地址族·Socklen_t套接口地址结构的长度,一般为uint32_t
In_addr_tIPv4地址,一般为uint32_t
In_port_tTCP或UDP端口,一般为uint16_t
Sin_zero成员暂时不适用设置为全0
套接口地址结构仅在主机上使用:
结构本身不参与通信
通用套接口地址结构:
Structsockaddr{
Uint8_tsa_len;
Sa_family_tsa_family;//addressfamily;AF_xxxvalue
Charsa_data[14];//protocol-specificaddress
}
内核根据sa_family的值确定指针的类型
IPv6套接口地址结构:
Structin6_addr{
Uint8_ts6_addr[16];//128位IPv6地址
}
#defineSIN6_LEN//requiredforcompile-timetests
Structsockaddr_in6{
Uint8_tsin6_len;//结构的长度(24)
Sa_family_tsin6_family;//AF_INET6
In_port_tsin6_port;//transportlayerport#
//网络字节序
Uint32_tsin6_flowinfo;//priority&flowlabel
//网络字节序
Structin6_addrsin6_addr;//IPv6地址
//网络字节序
}
如果系统支持套接口地址结构长度成员,则SIN6_LEN常值必须定义
Sin6_flowinfo成员分三个字段:
低24位是流量标号;
下4位是优先级;
在下4位保留
套接口地址结构的比较:
IPv4,IPv6,Unix域和数据链路
前两个长度固定,后两个长度可变.可变的话长度通过参数传递进函数
值-结果参数:
1.从进程到内核传递套接口地址结构3个套接口函数:
Bind,Connect,Sendto
Connect第一个参数是socket标志,2套接口地址结构指针3结构的大小(值传递)
套接口地址结构大小数据类型是socklen_t,Posix将其定义为uint32_t
2.从内核到进程传递套接口地址结构的4个套接口函数:
Accept,Recvfrom,Getpeername,Getsockname
套接口地址大小传递的是指针
Structsockaddr_uncli;//unixdomain
Socklen_tlen;
len=sizeof(cli);
getpeername(unixfd,(SA*)&cli,&len);
字节序转换函数:
字节操作函数:
ANSIC函数:
源与目标重叠时,bcopy能够正确处理,而memcpy是不可预知的,必须用memmove函数。
inet_atoninet_addrinet_ntoa函数
ASCII码与网络字节序二进制转换
inet_pton和inet_ntop对IPv4和IPv6地址都能处理。
Len的值在头文件中有定义:
#defineINET_ADDRSTRLEN16//IPv4地址ASCII码长度
#dedineINET6_ADDRSTRLEN46//IPv6地址ASCII码长度
如果len太小,则返回空字符,置errno为ENOSPC
小结:
对字节流套接口的读写:
判断描述字类型:
fdtype
在头文件中定义了大量的S_IFxxx常值
Socket函数:
TCP通信客户端,服务器端流程:
协议族类型和流类型
Socket函数成功时返回一个文件描述字。
AF_xxx与PF_xxx
AF_前缀代表地址族,PF_前缀代表协议族。
历史想法:
单个协议族支持多个地址族。
PF_值用来创建套接口,
而AF_值用于套接口地址结构。
现实中是AF_值与PF_值相等。
connect函数
客户端连接服务器时
第二个参数:
必须含有服务器的IP地址和端口号
客户端不必非得调用函数bind因为内核会选择源IP地址和一个临时的端口
每当函数返回失败,都必须关闭套接口描述字,重新调用socket。
Bind函数
可以指定一个端口号,指定一个IP地址,可以两者都指定,可以都不指定。
如果不指定,当调用函数connect和listen时,内核分配临时的端口号。
给函数bind指定用于绑定的IP地址和端口号的结果
IPv4通配地址由常值INADDR_ANY来指定。
其值一般为0
IPv4:
IPv6:
In6addr_any初始化为常值:
IN6ADDR_ANY_INIT在头文件:
中
中定义的INADDR_常值都是主机字节序的,应该使用htonl
为查看内核绑定的临时端口号可以调用getsockname来返回协议地址查看
listen函数
一般的,此函数在调用socket和bind之后,调用accept之前调用。
Backlog是已完成连接队列(ESTABLISHED状态)和未完成连接队列(SYN_RCVD状态)之和的最大值
accept函数
accept函数有TCP服务器调用,从已完成连接队列头返回下一个已完成连接。
若已完成连接队列为空,则进程睡眠(假定套接口为缺省的阻塞方式)。
函数的最大的返回值是连接套接口描述字,客户进程协议地址clladdr,协议长度addrlen
参数一是监听套接口描述字
Fork和exec函数
父进程调用fork之前打开的所有描述字在函数fork返回之后是共享的。
六个exec函数之间的区别:
A.被执行的程序是由文件名(filename)还是路径名(pathname)指定
B.新程序的参数是——列出还是有一个指针数组来索引
C.调用进程的环境传递给新程序还是指定新环境
其中,一般的只有execve是内核的系统调用,其他函数都是调用execve的库函数
一般来说,描述字在exec之前打开的在跨exec过程保持打开。
但可以用函数fcntl设置FD_CLOSEXEC描述字来关闭。
并发服务器。
为什么父进程close掉套接口描述字之后子进程共享的套接口描述字还可以使用?
答:
因为每个文件或套接口都有一个访问计数,该计数在文件表项中维护,它表示当前指向该文件或套接口的打开的描述字个数。
从socket返回后,文件表项访问计数值是1,accept返回还是1,fork返回后,两个描述字在父子进程间共享(即复制),所以,与两个套接口相关联的文件表项访问计数值均为2。
当父进程关闭描述符,只是将访问计数值从2减为1。
描述字只在访问计数达到0时才真正的关闭。
如果确实想对TCP连接发一个FIN,可以改用shutdown而不是close.
Close函数
#include
Intclose(intsockfd);
getsockname和getpeername函数
这两个函数返回与套接口关联的本地协议地址,或者返回与套接口关联的远程协议地址。
getsockname返回内核分配给此连接的本地IP地址和本地端口号。
getsockname可以获得某套接口的地址族。
在绑定一个通配IP地址的TCP服务器上,一旦与客户建立了连接,就可以调用getsockname来获取分配给此连接的本地IP地址。
在这样的调用中套接口描述字参数必须是已连接的套接口描述字,而不是监听套接口的描述字。
当一个服务器由调用accpet进程调用exec启动执行时,它获得客户身份的唯一途径便是调用getpeername。
exec执行的程序中获取监听套接字的方法:
1.通过调用exec的进程可以将描述字号格式化为一个字符串,并将它作为一个命令行参数传递给新程序;
2.确立调用exec前把某个描述字总是设定成已连接套接口的约定。
第5章TCP客户-服务器程序例子
111页。
Wait和waitpid函数
#include
pid_twait(int*statloc)
pid_twaitpid(pid_tpid,int*statloc,intoptions);
信号处理自定义函数:
Signal