免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 蓝色键盘
打印 上一主题 下一主题

*******网络编程基础( 讨论版V1 )******* [复制链接]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
11 [报告]
发表于 2003-04-02 22:39 |只看该作者

*******网络编程基础( 讨论版V1 )*******

3、IPv4和IPv6都属于网际协议(所有的网际协议由多个RFC定义),其版本有0、1、2、3和5,但是比较通用的是版本4和6。
版本4是80年代以后使用的比较广泛的主力协议,版本4使用32位的地址结构,主要给TCP、UDP、ICMP和IGMP提供传输分组的服务。
版本6是90年代中期设计出来的,主要变化是使用了128位的大地址结构,版本6主要给TCP、UDP和ICMPv6提供传输分组的服务。
在目前的应用中,有同时支持IPv4和IPv6的,一般称其为“IPv4/IPv6主机”或者"双栈主机"。
对于这两种协议之间的差别,可以到相关的系统中去察看,一般的在/usr/include/netinet/in.h中,各个系统定义的不尽相同,比如对于结构sockaddr_in中成员sin_len,sin_family和sin_port的数据类型的定义在很多unix系统中的定义有一定的差别,不过对于使用者来说,你只要关心它的大小就可以了,至于到底定义为哪一种类型,同样的可以到系统头文件中可以找得到。在Posix.1g中定义的套接口地址结构如下:
IPv4的定义:
struct in_addr {
in_addr_t s_addr;
};
struct sockaddr_in{
unit8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
其中成员sin_zero暂时没有使用到,用来扩充功能,一般在使用时将其初始化为0,事实上,Posix.1g只需要这个结构中的三个成员sin_family、sin_port和sin_addr,加入其他的两项完全是为了兼容性考虑的。在此强调,这个结构中重要的是结构的大小至少要求16字节,每个具体的成员的大小,请到你的系统中去察看,这里不再赘述。
需要说明的是:在实际的网络通讯中,该结构并不参与通信,尽管成员sin_port和sin_addr用在不同主机间的通信中。
IPv6的定义:
struct in6_addr {
unit8_t s6_addr[16];
};
#define SIN6_LEN
struct sockaddr_in6{
unit8_t sin6_len;
sa_family_t sin6_family;
in_port_t sin6_port;
unit32_t sin6_flowinfo;
struct in6_addr sin6_addr;

};
该结构比较特殊的是成员sin6_flowinfo,事实上该成员的32位用来表示不同的含义,如流量控制(低24位)、优先级(下4位)等。
以上所定义的结构,在我们实际的网络编程中,往往要作为某一个套接口函数的参数来使用,由于历史的原因和为了消除特定协议之间的差别,引入了所谓的通用套接口地址结构,定义如下:
struct sockaddr {
unit8_t sa_len;
sa_family_t sa_family;
char sa_data[14];
};
该结构一般的定义在/usr/include/sys/socket.h中,并且在很多系统中套接口函数原型的定义也使用该通用结构,如 int bind(int s, const struct sockaddr *addr, socklen_t addrlen);,这样在我们编写程序的时候,需要将只想特定协议的地址结构的指针类型转化为该通用套接口地址结构,例如:
struct sockaddr_in testserv;
/* other code */
if( ( ret = connect( sockfd, (struct sockaddr * )&amp;testserv,sizeof( testserv ) ) ) < 0 ) {
close(sockfd);
if( errno == EINTR ) {
errno = ETIMEDOUT;
continue;
}
}
/* other code */
以上简单的描述了IPb4和IPv6地址结构之间的差别,以及通用地址结构的使用。

有关两者互操作的下次补充(我要休息了,累!)

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
12 [报告]
发表于 2003-04-03 00:15 |只看该作者

*******网络编程基础( 讨论版V1 )*******

原帖由 "蓝色键盘" 发表:

感谢gadfly对状态转化图的引入,不知道gadfly能否就TIME_WAIT和CLOE_WAIT和FIN_WAIT_1这三种状态做些描述,建议主要针对以下两方面来做描述:
(1)、该状态在什么情况下出现。
(2)、TCP为什么要引入该状态,分别对应与那些处理细节


我就试着用上图解释,错了不要拍砖啊. 请各位纠正和补充。

正常情况下,
主动关闭的一端发出FIN请求后(close or shotdown),主动关闭的一端就进入这个状态,
FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;


被动关闭的一方接到FIN后,就发出ACK,并进入
CLOSE-WAIT - 等待足够的时间以确保远程TCP接收到连接中断请求的确认;

被动关闭的一方接着又发送FIN包,就进入了
LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;

主动关闭的一方接到ACK后,就进入了
FIN-WAIT-2 - 从远程TCP等待连接中断请求;

在主动的一方接收到FIN后,就发送ACK包,并进入TIME-WAIT状态。2MSL后进入closed

被动一方在接受到ACK包后,就进入了closed的状态。


TIME_WAIT状态状态也称为2MSL等待状态。MSL是TCP报文的生存时间,这样可让TCP再次发送最后的ACK以防这个ACK丢失(加入丢失,另一端超时并重发最后的FIN)。设想一下,
如果这个状态时间不足够长,如果ACK丢失,同时主动方的这个端口又重用了,对方因为
没有收到FIN的ACK,所以就重发FIN,有可能导致主动方连接的错误关闭。

如果是服务器被终止,并试图立即重新启动这个服务器程序的话,就可能发生经常出现的错误:can't bind local address: address already in use. 就是因为端口处于TIME_WAIT状态。不过可以通过设置选项SO_REUSEADDR来避免这种错误。


如果想了解的更透彻一些,建议通读TCP/IP详解 卷一的18章.

论坛徽章:
0
13 [报告]
发表于 2003-04-03 12:38 |只看该作者

*******网络编程基础( 讨论版V1 )*******

大家都讨论得很激烈
看来论坛中还是藏龙卧虎之地很不错

另外
如果client发送的数据被路由丢弃或者服务器的应答信息丢失,那么client将一直阻塞,直到应用设置的超时到达

我觉得UDP就是发送以后不管的
只是向UDP端口写完数据后就返回
不会等待是不是发送成功

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
14 [报告]
发表于 2003-04-03 13:11 |只看该作者

*******网络编程基础( 讨论版V1 )*******

client在sendto后,需要recvfrom(除非你的这个UDP应用只发送数据不接收数据),对于服务端来的响应信息client是一直阻塞的(除非应用设置了超时),因而不论是client发送的数据被路由丢弃还是服务器的应答信息丢失,client都无法得知这些信息,这种情况对于异步错误也是一样的。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
15 [报告]
发表于 2003-04-03 13:35 |只看该作者

*******网络编程基础( 讨论版V1 )*******

原帖由 "无双" 发表:

我觉得UDP就是发送以后不管的
只是向UDP端口写完数据后就返回
不会等待是不是发送成功


同意你的观点,研究了一下,udp的输出队列有数据后,就会放到interface的
buf中,如果interface的buf满了,至少在linux上的处理是直接丢弃(参看sendto 的man ENOBUFS,和TCP/IP详解1的23)。在windows上缺省的buf满后,倒是会阻塞并等待。

而输入队列也有这个问题。如果发送方过快,即使数据到达对方主机,如果输入buf慢的话,udp包也是会丢失的。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
16 [报告]
发表于 2003-04-03 13:39 |只看该作者

*******网络编程基础( 讨论版V1 )*******

[quote]原帖由 "蓝色键盘"]client在sendto后,需要recvfrom(除非你的这个UDP应用只发送数据不接收数据),对于服务端来的响应信息client是一直阻塞的(除非应用设置了超时),因而不论是client发送的数据被路由丢弃还是服务器的应答信息丢失?.........[/quote 发表:



如果你这么说,只是说recvfrom会阻塞,而不是指sendto调用.

我想我和无双指的都是单个的sendto系统调用.

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
17 [报告]
发表于 2003-04-03 14:01 |只看该作者

*******网络编程基础( 讨论版V1 )*******

对于sendto而言,是非阻塞的,如果发送的msg为0,它也能够成功,这时候发送的仅仅是一个IP头部和一个UDP头和一个空的数据报,即使在sendto中没有指明bind的IP和PORT,UDP会让系统来选择一个localhost和随机的Port填充结构 const struct sockaddr *to。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
18 [报告]
发表于 2003-04-03 14:15 |只看该作者

*******网络编程基础( 讨论版V1 )*******

对于recvfrom而言,是阻塞的(除非设置超时),unix95中原型如下:
ssize_t recvfrom( int  s,void  *buf,size_t  len,int  flags,struct sockaddr *from,size_t  *fromlen)
和sendto返回类型一样,recvfrom返回的是接受到的数据报大小。参数from和fromlen可以指定,也可以不指定,如果指定那么UDP用它来标识数据报的发送者是谁。该函数是从接受缓冲区接受数据报(如果缓冲区有数据报的话),如果RECVBUF没有数据,那么将阻塞。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
19 [报告]
发表于 2003-04-03 14:22 |只看该作者

*******网络编程基础( 讨论版V1 )*******

上面的关闭序列中,我只是列举了单方主动关闭的情况.

大家还可以研究一下双方同时主动关闭,以及单方半关闭的情况,这样能更好的理解shutdown,close的实现机制

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
20 [报告]
发表于 2003-04-03 18:01 |只看该作者

*******网络编程基础( 讨论版V1 )*******

上面的5个问题只有4缺少完整讨论,这个留给其他的兄弟吧!总不能就我们几个说来说去,呵呵
接下来,谈论第二版V2。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP