当前位置:  技术问答>linux和unix

Shutdown和Select的困惑

    来源: 互联网  发布时间:2016-07-23

    本文导语:  小弟是菜鸟,最近学习《UNIX网络编程》第三版。读到IO复用那章,6.6,6.7讲shutdown用法的地方,有点困惑。 按照书上说,SHUT_RD是关闭连接读的一半,套接口中不再有数据可接收,而且套接口接受缓冲区中的现有数据...

小弟是菜鸟,最近学习《UNIX网络编程》第三版。读到IO复用那章,6.6,6.7讲shutdown用法的地方,有点困惑。
按照书上说,SHUT_RD是关闭连接读的一半,套接口中不再有数据可接收,而且套接口接受缓冲区中的现有数据都被丢弃。进程不能再对这样的套接口调用任何读函数。套接口接收的来自对端的任何数据都被确认,然后悄悄丢弃。
我为了试验SHUT_RD,就把6.7的str_cli中Shutdown(sockfd, SHUT_WR)改为了Shutdown(sockfd, SHUT_RD)。为了确认客户端退出状态,我还在return前面加了printf("normal terminationn");

客户端代码:tcpcli02.c

/* Use standard echo server; baseline measurements for nonblocking version */
#include "unp.h"

int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;

if (argc != 2)
err_quit("usage: tcpcli ");

sockfd = Socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT); //7
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));

str_cli(stdin, sockfd); /* do it all */

exit(0);
}


str_cli所在文件strcliselect02.c

#include "unp.h"

void
str_cli(FILE *fp, int sockfd)
{
int maxfdp1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n;

stdineof = 0;
FD_ZERO(&rset);
for ( ; ; ) {
if (stdineof == 0)
FD_SET(fileno(fp), &rset);
FD_SET(sockfd, &rset);
maxfdp1 = max(fileno(fp), sockfd) + 1;
Select(maxfdp1, &rset, NULL, NULL, NULL);

if (FD_ISSET(sockfd, &rset)) { /* socket is readable */
if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
if (stdineof == 1) {
                                        printf("normal terminationn");
                                        return; /* normal termination */
                                }
else
err_quit("str_cli: server terminated prematurely");
}
Write(fileno(stdout), buf, n);
}

if (FD_ISSET(fileno(fp), &rset)) {  /* input is readable */
if ( (n = Read(fileno(fp), buf, MAXLINE)) == 0) {
stdineof = 1;
Shutdown(sockfd,  SHUT_RD); /* send FIN SHUT_WR */
FD_CLR(fileno(fp), &rset);
continue;
}

Writen(sockfd, buf, n);
}
}
}



服务器是一个回射操作,只要客户端从stdio输入,服务器就返回给客户端一样的内容。

运行服务器和客户端,并且在客户端输入“test”和ctrl+d,结果如下:

wanjian@ubuntu:~/net/select$ ./tcpcli02 127.0.0.1
test
test
normal termination


整个连接建立和终止的tcpdump:

root@ubuntu:/home/wanjian# tcpdump -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes
22:00:43.922807 IP localhost.53342 > localhost.9877: Flags [S], seq 3927771684, win 32792, options [mss 16396,sackOK,TS val 328455 ecr 0,nop,wscale 5], length 0
22:00:43.925823 IP localhost.9877 > localhost.53342: Flags [S.], seq 3925328431, ack 3927771685, win 32768, options [mss 16396,sackOK,TS val 328456 ecr 328455,nop,wscale 5], length 0
22:00:43.929054 IP localhost.53342 > localhost.9877: Flags [.], ack 1, win 1025, options [nop,nop,TS val 328457 ecr 328456], length 0
22:01:00.022906 IP localhost.53342 > localhost.9877: Flags [P.], seq 1:6, ack 1, win 1025, options [nop,nop,TS val 332480 ecr 328456], length 5
22:01:00.025050 IP localhost.9877 > localhost.53342: Flags [.], ack 6, win 1024, options [nop,nop,TS val 332481 ecr 332480], length 0
22:01:00.026434 IP localhost.9877 > localhost.53342: Flags [P.], seq 1:6, ack 6, win 1024, options [nop,nop,TS val 332481 ecr 332480], length 5
22:01:00.026918 IP localhost.53342 > localhost.9877: Flags [.], ack 6, win 1025, options [nop,nop,TS val 332481 ecr 332481], length 0
22:01:30.425750 IP localhost.53342 > localhost.9877: Flags [F.], seq 6, ack 6, win 1025, options [nop,nop,TS val 340081 ecr 332481], length 0
22:01:30.430395 IP localhost.9877 > localhost.53342: Flags [F.], seq 6, ack 7, win 1024, options [nop,nop,TS val 340082 ecr 340081], length 0
22:01:30.432291 IP localhost.53342 > localhost.9877: Flags [.], ack 7, win 1025, options [nop,nop,TS val 340082 ecr 340082], length 0


从执行结果看,tcpdump中最后3个分组分别是客户端发给服务器的FIN,服务器发给客户端的FIN(捎带了ACK),客户端发给服务器的ACK。这3个分组还好理解,因为“套接口接收的来自对端的任何数据都被确认,然后悄悄丢弃”。但是为何最后客户端“normal termination”了呢?如果“套接口中不再有数据可接收”,那么为什么Select返回了并且检测到是sockfd可读呢?如果“进程不能再对这样的套接口调用任何读函数”,那么下面的Read为何读到了EOF而返回0呢?

请教大虾帮助!!!!

|
1.FIN包不算数据包,不会被丢弃。如果丢弃的话TCP连接就没法正常断开了
2.收到FIN包后,协议栈会设置相应sock为可读,但read会返回0表示EOF
3.shutdown只对本地socket数据的读写有影响,对正常的TCP协议流程没有影响

    
 
 

您可能感兴趣的文章:

 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • java命名空间java.util.concurrent类scheduledthreadpoolexecutor的类成员方法: shutdown定义及介绍
  • ubuntu fedora关机输入shutdown -P now就行。redhat怎么是用shutdown -h now关机
  • java命名空间java.rmi.activation接口activationsystem的类成员方法: shutdown定义及介绍
  • linux图形模式下shutdown里有Hibernate这个选项。怎么man shutdown里找不到hibernate这个选项呢。
  • java命名空间java.util.concurrent类threadpoolexecutor的类成员方法: shutdown定义及介绍
  • shutdown -H这个参数有什么用呢。shutdown -H now 出现system halted。 是不是只能通过按机箱reset键进行重启??
  • java命名空间java.util.concurrent接口executorservice的类成员方法: shutdown定义及介绍
  • linux shutdown
  • java命名空间javax.print.attribute.standard类printerstatereason的类成员方法: shutdown定义及介绍
  • 普通用户不能使用shutdown命令吗?
  • 请教有关linux下shutdown的一些问题
  • linux的shutdown会执行哪些操作读取哪些脚本哦?
  • Solaris/HP-UX平台socket API:shutdown问题
  • linux普通用户如何用shutdown命令
  • linux的shutdown命令
  • shutdown 和 halt 有什么区别
  • 我装了redhat7.2,为什么不能完全shutdown?
  • 为什么我的linux不能够再shutdown后自动关闭机器
  • shutdown命令的问题
  • 我的redhat没有shutdown命令
  • 求解啊,centos下 shutdown -h now 无效??


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3