socket 中read返回0的情况

摘要:
有两个原因:1.如果它没有关闭,父进程将消耗所有可用的描述符,因为它每次接受新连接时都必须返回一个新的未使用的fd,消耗资源,因为它阻止了终止序列FIN的发布。这两个参数的含义是:shutdown:SHUT_ RDserver端关闭连接的读取部分,并且该进程无法再对此类套接字调用任何读取操作。

当client,调用read(socketfd,buffer,n)时,返回0的情况:

1、server端调用了close(soketfd)函数

2、server调用了close(fd,SHUT_WR),关闭server端的写连接,半关闭

socket 中read返回0的情况第1张

关于close 和shutdown的过程

一.void close(fd):close发送的是FIN分节(不一定是发送FIN,也可能发送RST(如果local接受缓冲区的数据没有被读完);sever端close时候,如果发送了FIN,则这个sokcet在server端将不能够被read和write,会返回错误(如果有read或者write则返回errno9: Bad file descriptor错误)

默认状态,是把此套接字标记为关闭状态(真正只是把套接字的引用计数-1),close函数都立刻返回。如果引用计数为0,才开始发送四字节的FIN分节(连接终止序列),close在sever端调用之后,会立刻返回,同时尽力发送此时仍然在套接字发送缓冲区的发送数据,在此之后才会发出FIN四分节的连接终止序列。

扩展:在父子进程模型中,我们每次fork子进程之后,都需要在父进程中关闭连接套接字(connfd),而在子进程中都需要关闭监听套接字,此模型中accept在fork函数之前。

原因有两点:

1、如果不关闭,则父进程将消耗所以的可用描述符,因为它每次accept新连接,都得返回一个新的未用的fd

2.如果不关父进程中的connfd,则父子进程的引用计数都保持在2,即便子进程关闭,只是把引用计数-1,这样由于父进程正常情况永远不会关闭,所以这些连接其实永远都不会关闭,消耗资源,因为这阻挡了终止序列FIN的发出。

二:shutdown(int fd,int how)

close是关闭读写两个方向的数据传输,而shutdown指定关闭SHUT_WRS称为半关闭,只关闭一个方向,另一个方向依然可用。

两个参数的意思:

shutdown:SHUT_RD

server端关闭连接的读这一半,进程不能再对这样的套接字调用任何操作(如果有read则返回errno9: Bad file descriptor错误)。这个SHUT_RD标志告诉内核,我绝食了,再有吃的来(数据),不要放我的餐桌上了(接收缓冲区)直接扔给狗吃把。(但是此时client还是可以发送给server套接字的接收缓冲区,只是被TCP抛弃而已)

套接字不再有数据可接受,server不能调用read,server进程仍可往套接字发送数据,server套接字接收缓冲区中所有数据被丢弃,再接收到的任何数据都被TCP丢弃,对套接字发送缓冲区没有任何影响;

shutdown:SHUT_WR(又叫做半关闭):与close不同的是,无论引用计数是否为0,这样的操作都进行,此后server进程不能对此套接字进行写操作)

当前server套接字发送缓冲区中的内容被发送到对端,后跟正常的TCP连接终止序列(即发送FIN),

关闭连接的写这一半,进程不能再对这样的套接字调用任何操作;(如果server有write则返回errno9: Bad file descriptor错误)

在server的套接字上不能再发出发送请求,进程仍可从套接字接收数据,当前server套接字发送缓冲区中的内容被发送到对端,后跟正常的TCP连接终止序列(即发送FIN),对套接字接收缓冲区无任何影响;

注意:1.server端,close调用之后如果在local TCP buffer内如果还有数据没有读取会给对方,则主动直接发送RST给client, 否则发送FIN,这取决于调用close时刻local TCP buffer的状态, 跟对端是不是继续发送数据无关。

2. shutdown关闭读不会给对方发FIN, 只有关闭写才会发FIN, 而且跟local TCP buffer状态没关系,只发送FIN包,从不发送RST

总结:shutdown从不发送RST给对端(只发送FIN),只有close在接收缓存区没有被读完的条件下,才发送给对端RST。

免责声明:文章转载自《socket 中read返回0的情况》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇2.变量Java Array二维数组使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ADO.NET访问数据库SqlCommand的ExecuteReader方法一般配合sqldatareader使用

用于执行查询语句并返回一个DataReader类型的行集合. 在与数据库交互中,要获得数据访问的结果可用连载方法实现,一个是datareader对象从数据源中获得数据并进行处理;另一种是通过dataset对象将数据存放在内存中进行处理 datareader可以顺序地查询结果集中读取记录,他的特点是单向向前,速度快占用内存少。使用datareader对象无论...

TCP/IP网络编程系列之三(初级)

TCP/IP网络编程系列之三-地址族与数据序列 分配给套接字的IP地址和端口 IP是Internet Protocol (网络协议)的简写,是为首发网络数据而分配给计算机的值。端口号并非赋予计算机值,而是为了区分程序中创建的套接字而分配给套接字的序号。 网络地址 网络地址分为IPV4和IPV6,分别你别为4个字节地址簇和6个字节地址簇。IPV4标准的4个字...

UNIX网络编程——网络IPC:套接字

Contents 套接字接口 套接字描述符 寻址 字节序 地址格式 地址查询 绑定地址 建立连接 数据传输 套接字选项 带外数据 UNIX域套接字 使用套接字的示例 面向连接的ruptime 无连接的ruptime 套接字接口       套接字接口是一组用来结合UNIX I/O函数进行进程间通信的函数,大多数系统上都实现了它,包括各...

[Python之路] 使用epoll实现高并发HTTP服务器

什么是epoll 我们在  Python多种方式实现并发的Web Server 的最后使用单进程+单线程+非阻塞+长连接实现了一个可并发处理客户端连接的服务器。他的原理可以用以下的图来描述: 解释: 1.HTTP服务器是我们使用 单进程+单线程+非阻塞+长连接实现 的web服务器。 2.在实现的时候,我们创建了一个存放已接受Socket连接的列表,该列表...

[转]慎用InputStream的read()方法

InputStream此抽象类是表示字节输入流的所有类的超类。 我们从输入流中读取数据最常用的方法基本上就是如下3个read()方法了: 1、read()方法,这个方法从输入流中读取数据的下一个字节。返回 0到255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回值-1。 2、read(byte[]b,intoff,intlen)方法...

【python】udp 数据的发送和接收

import socket def send_message(): # 创建一个udp套接字 udp_socker = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 发送数据,从键盘获取数据 send_data = input("请输入要发送的数据:")...