close只是减少描述符的引用计数,计数为0才真正关闭套接字;shutdown为立即关闭。close并不保证文件写入磁盘,如需要的话要调用sync 或fsync.
shutdown可以指定参数,只关闭读端或者写端。而close是双端关闭(请求断开连接,认为另一端也没有需要传送的内容了)。
close之后tcp将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的tcp连接终止序列。
可以设置SO_LINGER选项来改变TCP套接字的这种默认行为。具体可以查看man手册。下面是一个简单说明:
SO_LINGER:
指定close关闭套接字的操作:close的默认动作是如果有数据残留在套接字发送缓冲区中,系统将试着把这些数据发送给对端。
SO_LINGER选项可以改变这个默认设置。其中linger结构如下:
struct linger{
intl_onoff; //0=off, nonzero=on
intl_linger; //linger time
};
根据struct linger中l_onoff和l_linger的取值,有下面三种情况:
1) l_onoff选项为0,那么关闭该选项,即仍保留tcp套接字的默认行为。
2) l_onoff非零且l_linger为0,那么close某个连接时tcp将中止该连接,即丢弃套接字发送缓冲区的任何数据,并发送一个rst给对端,而没有通常的四分组连接中止序列。 (这样一来避免了TCP的TIME_WAIT状态)。存在的问题是:可能带来2MSL的问题。
3) l_onoff非零且l_linger非0,等待数据发送完关闭或者时间到关闭。这两种情况可通过close的返回值进行判断,后一种情况返回EWOILDBLOCK错误。