)
如果flags为0,则和read,write一样的操作.还有其它的几个选项,不过我们实际上用的很
少,可以查看 linux programmer's manual得到详细解释.
6.2 recvfrom和sendto
这两个函数一般用在非套接字的网络程序当中(udp),我们已经在前面学会了.
6.3 recvmsg和sendmsg
recvmsg和sendmsg可以实现前面所有的读写函数的功能.
int recvmsg(int sockfd,struct msghdr *msg,int flags)
int sendmsg(int sockfd,struct msghdr *msg,int flags)
struct msghdr
{
void *msg_name;
int msg_namelen;
struct iovec *msg_iov;
int msg_iovlen;
void *msg_control;
int msg_controllen;
int msg_flags;
}
struct iovec
{
void *iov_base; /* 缓冲区开始的地址 */
size_t iov_len; /* 缓冲区的长度 */
}
msg_name和 msg_namelen当套接字是非面向连接时(udp),它们存储接收和发送方的地址
信息.msg_name实际上是一个指向struct sockaddr的指针,msg_name是结构的长度.当套
接字是面向连接时,这两个值应设为null. msg_iov和msg_iovlen指出接受和发送的缓冲
区内容.msg_iov是一个结构指针,msg_iovlen指出这个结构数组的大小. msg_control和
msg_controllen这两个变量是用来接收和发送控制数据时的 msg_flags指定接受和发送
的操作选项.和recv,send的选项一样
6.4 套接字的关闭
关闭套接字有两个函数close和shutdown.用close时和我们关闭文件一样.
6.5 shutdown
int shutdown(int sockfd,int howto)
tcp连接是双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希
望只关闭一个方向,这个时候我们可以使用shutdown.针对不同的howto,系统回采取不同
的关闭方式.
howto=0这个时候系统会关闭读通道.但是可以继续往接字描述符写.
howto=1关闭写通道,和上面相反,着时候就只可以读了.
howto=2关闭读写通道,和close一样 在多进程程序里面,如果有几个子进程共享一个套接
字时,如果我们使用shutdown, 那么所有的子进程都不能够操作了,这个时候我们只能够
使用close来关闭子进程的套接字描述符.
网络编程(7)
7. tcp/ip协议
你也许听说过tcp/ip协议,那么你知道到底什么是tcp,什么是ip吗?在这一章里面,我们一
起来学习这个目前网络上用最广泛的协议.
7.1 网络传输分层
如果你考过计算机等级考试,那么你就应该已经知道了网络传输分层这个概念.在网络上
,人们为了传输数据时的方便,把网络的传输分为7个层次.分别是:应用层,表示层,会话层
,传输层,网络层,数据链路层和物理层.分好了层以后,传输数据时,上一层如果要数据的
话,就可以直接向下一层要了,而不必要管数据传输的细节.下一层也只向它的上一层提供
数据,而不要去管其它东西了.如果你不想考试,你没有必要去记这些东西的.只要知道是
分层的,而且各层的作用不同.
7.2 ip协议
ip协议是在网络层的协议.它主要完成数据包的发送作用. 下面这个表是ip4的数据包格
式
0 4 8 16 32
--------------------------------------------------
|版本 |首部长度|服务类型| 数据包总长 |
--------------------------------------------------
| 标识 |df |mf| 碎片偏移 |
--------------------------------------------------
| 生存时间 | 协议 | 首部较验和 |
------------------------------------------------
| 源ip地址 |
------------------------------------------------
| 目的ip地址 |
-------------------------------------------------
| 选项 |
=================================================
| 数据 |
-------------------------------------------------
下面我们看一看ip的结构定义<netinet/ip.h>
struct ip
{
#if __byte_order == __little_endian
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
#if __byte_order == __big_endian
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define ip_rf 0x8000 /* reserved fragment flag */
#define ip_df 0x4000 /* dont fragment flag */
#define ip_mf 0x2000 /* more fragments flag */
#define ip_offmask 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
};
ip_vip协议的版本号,这里是4,现在ipv6已经出来了
ip_hlip包首部长度,这个值以4字节为单位.ip协议首部的固定长度为20个字节,如果ip包
没有选项,那么这个值为5.
ip_tos服务类型,说明提供的优先权.
ip_len说明ip数据的长度.以字节为单位.
ip_id标识这个ip数据包.
ip_off碎片偏移,这和上面id一起用来重组碎片的.
ip_ttl生存时间.没经过一个路由的时候减一,直到为0时被抛弃.
ip_p协议,表示创建这个ip数据包的高层协议.如tcp,udp协议.
ip_sum首部校验和,提供对首部数据的校验.
ip_src,ip_dst发送者和接收者的ip地址
关于ip协议的详细情况,请参考 rfc791
7.3 icmp协议
icmp是消息控制协议,也处于网络层.在网络上传递ip数据包时,如果发生了错误,那么就
会用icmp协议来报告错误.
icmp包的结构如下:
0 8 16 32
---------------------------------------------------------------------
| 类型 | 代码 | 校验和 |
--------------------------------------------------------------------
| 数据 | 数据 |
--------------------------------------------------------------------
icmp在<netinet/ip_icmp.h>中的定义是
struct icmphdr
{
u_int8_t type; /* message type */
u_int8_t code; /* type sub-code */
u_int16_t checksum;
union
{
struct
{
u_int16_t id;
u_int16_t sequence;
} echo; /* echo datagram */
u_int32_t gateway; /* gateway address */
struct
{
u_int16_t __unused;
u_int16_t mtu;
} frag; /* path mtu discovery */
} un;
};
关于icmp协议的详细情况可以查看 rfc792
7.4 udp协议
udp协议是建立在ip协议基础之上的,用在传输层的协议.udp和ip协议一样是不可靠的数
据报服务.udp的头格式为:
0 16 32
---------------------------------------------------
| udp源端口 | udp目的端口 |
---------------------------------------------------
| udp数据报长度 | udp数据报校验 |
---------------------------------------------------
udp结构在<netinet/udp.h>中的定义为:
stru