TCP send 阻塞与非阻塞

http://blog.chinaunix.net/uid-8489474-id-2031025.html

 

tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据.

在阻塞模式下, send函数的过程是将应用程序请求发送的数据拷贝到发送缓存中发送就返回.但由于发送缓存的存在,表现为:如果发送缓存大小比请求发送的大小要大,那么send函数立即返回,同时向网络中发送数据;否则,send会等待接收端对之前发送数据的确认,以便腾出缓存空间容纳新的待发送数据,再返回(接收端协议栈只要将数据收到接收缓存中,就会确认,并不一定要等待应用程序调用recv),如果一直没有空间能容纳待发送的数据,则一直阻塞;

在非阻塞模式下,send函数的过程仅仅是将数据拷贝到协议栈的缓存区而已,如果缓存区可用空间不够,则尽能力的拷贝,立即返回成功拷贝的大小;如缓存区可用空间为0,则返回-1,同时设置errno为EAGAIN.

 

需要注意的是,虽然将发送缓存设置成了10k,但实际上,协议栈会将其扩大1倍,设为20k.


应用程序表现如下:

在实际应用中,如果发送端是非阻塞发送,由于网络的阻塞或者接收端处理过慢,通常出现的情况是,发送应用程序看起来发送了10k的数据,但是只发送了2k到 对端缓存中,还有8k在本机缓存中(未发送或者未得到接收端的确认).那么此时,接收应用程序能够收到的数据为2k.假如接收应用程序调用recv函数获 取了1k的数据在处理,在这个瞬间,发生了以下情况之一,双方表现为:

A. 发送应用程序认为send完了10k数据,关闭了socket:
发送主机作为tcp的主动关闭者,连接将处于FIN_WAIT1的半关闭状态(等待对方的ack),并且,发送缓存中的8k数据并不清除,依然会发送给对 端.如果接收应用程序依然在recv,那么它会收到余下的8k数据(这个前题是,接收端会在发送端FIN_WAIT1状态超时前收到余下的8k数据.), 然后得到一个对端socket被关闭的消息(recv返回0).这时,应该进行关闭.

B. 发送应用程序再次调用send发送8k的数据:
假如发送缓存的空间为20k,那么发送缓存可用空间为20-8=12k,大于请求发送的8k,所以send函数将数据做拷贝后,并立即返回8192;

假如发送缓存的空间为12k,那么此时发送缓存可用空间还有12-8=4k,send()会返回4096,应用程序发现返回的值小于请求发送的大小值后,可以认 为缓存区已满,这时必须阻塞(或通过select等待下一次socket可写的信号),如果应用程序不理会,立即再次调用send,那么会得到-1的值, 在linux下表现为errno=EAGAIN.

C. 接收应用程序在处理完1k数据后,关闭了socket:
接收主机作为主动关闭者,连接将处于FIN_WAIT1的半关闭状态(等待对方的ack).然后,发送应用程序会收到socket可读的信号(通常是 select调用返回socket可读),但在读取时会发现recv函数返回0,这时应该调用close函数来关闭socket(发送给对方ack);

如果应用程序通过select()函数仅检测该socket句柄是否可写,它会返回应用层可写.
假设发送应用程序收到可读或可写的信号后,继

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线程终止

进程终止时exit()函数,那么线程终止的是什么呢? 线程终止的三种情况: 线程只是从启动函数中返回,返回的是线程的退出码;线程可以被同一进程中的其他线程取消;线程调用pthread_exit。/*** exit.c ***/ #incl…

linux下recv 、send阻塞、非阻塞区别和用法

非阻塞IO 和阻塞IO: 在网络编程中对于一个网络句柄会遇到阻塞IO 和非阻塞IO 的概念, 这里对于这两种socket 先做一下说明: 基本概念: 阻塞IO:: socket 的阻塞模式意味着必须要做完IO 操作(包括错误)才会返回。 …

linux非阻塞的socket发送数据出现EAGAIN错误的处理方法

一、非阻塞socket 非阻塞套接字是指执行此套接字的网络调用时,不管是否执行成功,都立即返回。比如调用recv()函数读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。在实际Windows网络通信软件开发中…

线程取消

int pthread_cancel(pthread_t th); 该函数运行一个线程取消指定的另一个线程th 函数成功&#xff0c;返回0&#xff0c;否则&#xff0c;返回非0&#xff1b; /*** cancel.c ***/ #include<stdio.h> #include<pthread.h> #include<errno.h> #include<str…

Linux下的I/O复用与epoll详解(ET与LT)

前言 I/O多路复用有很多种实现。在linux上&#xff0c;2.4内核前主要是select和poll&#xff0c;自Linux 2.6内核正式引入epoll以来&#xff0c;epoll已经成为了目前实现高性能网络服务器的必备技术。尽管他们的使用方法不尽相同&#xff0c;但是本质上却没有什么区别。本文将重…

彻底学会使用epoll(一)——ET模式实现分析

注&#xff1a;之前写过两篇关于epoll实现的文章&#xff0c;但是感觉懂得了实现原理并不一定会使用&#xff0c;所以又决定写这一系列文章&#xff0c;希望能够对epoll有比较清楚的认识。是请大家转载务必注明出处&#xff0c;算是对我劳动成果的一点点尊重吧。另外&#xff0…

OPENSSL X509证书验证

openssl实现了标准的x509v3数字证书&#xff0c;其源码在crypto/x509和crypto/x509v3中。其中x509目录实现了数字证书以及证书申请相关的各种函数&#xff0c;包括了X509和X509_REQ结构的设置、读取、打印和比较&#xff1b;数字证书的验证、摘要&#xff1b;各种公钥的导入导出…

linux网络编程九:splice函数,高效的零拷贝

1. splice函数 #include <fcntl.h> ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags); splice用于在两个文件描述符之间移动数据&#xff0c; 也是零拷贝。 fd_in参数是待输入描述符。如果它是一个管道文件…

sys/queue.h

概述 sys/queue.h是LINUX/UNIX系统下面的一个标准头文件&#xff0c;用一系列的数据结构定义了一队列。包括singly-lined list, list, simple queue(Singly-linked Tail queue), tail queue, circle queue五种。 引用此头文件对这五种数据结构的描述&#xff1a; A singly-lin…

sys/queue.h分析(图片复制不过来,查看原文)

这两天有兴趣学习使用了下系统头文件sys/queue.h中的链表/队列的实现&#xff0c;感觉实现的很是优美&#xff0c;关键是以后再也不需要自己实现这些基本的数据结构了&#xff0c;哈哈&#xff01; 我的系统环境是 正好需要使用队列&#xff0c;那么本篇就以其中的尾队列&…

线程池原理及C语言实现线程池

备注&#xff1a;该线程池源码参考自传直播客培训视频配套资料&#xff1b; 源码&#xff1a;https://pan.baidu.com/s/1zWuoE3q0KT5TUjmPKTb1lw 密码&#xff1a;pp42 引言&#xff1a;线程池是一种多线程处理形式&#xff0c;大多用于高并发服务器上&#xff0c;它能合理有效…

iptables 的mangle表

mangle表的主要功能是根据规则修改数据包的一些标志位&#xff0c;以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。 内网的客户机通过Linux主机连入Internet&#xff0c;而Linux主机与Internet连接时有两条线路&#xff0c;它们的网关如图所示。现要求对内网进…

Linux常用命令(一)

history 查看历史命令 ctrlp 向上翻历史纪录 ctrln 向下翻历史纪录 ctrlb 光标向左移动 ctrlf 光标向右移动 ctrla 光标移动到行首 ctrle 光标移动到行尾 ctrlh 删除光标前一个 ctrld 删除光标后一个 ctrlu 删除光标前所有 ctrlL clear命令 清屏 tab键可以补全命令/填充路径…

ip route / ip rule /iptables 配置策略路由

Linux 使用 ip route , ip rule , iptables 配置策略路由 要求192.168.0.100以内的使用 10.0.0.1 网关上网&#xff0c;其他IP使用 20.0.0.1 上网。 首先要在网关服务器上添加一个默认路由&#xff0c;当然这个指向是绝大多数的IP的出口网关。 ip route add default gw 20.0.0.…

iptables:tproxy做透明代理

什么是透明代理 客户端向真实服务器发起连接&#xff0c;代理机冒充服务器与客户端建立连接&#xff0c;并以客户端ip与真实服务器建立连接进行代理转发。因此对于客户端与服务器来说&#xff0c;代理机都是透明的。 如何建立透明代理 本地socket捕获数据包 nat方式 iptables…

编译参数(-D)

程序中可以使用#ifdef来控制输出信息 #include<stdio.h> #define DEBUGint main() {int a 10;int b 20;int sum a b; #ifdef DEBUGprintf("%d %d %d\n",a,b,sum); #endifreturn 0; } 这样在有宏定义DEBGU的时候就会有信息输出 如果注销掉宏定义就不会有输…

libpcap讲解与API接口函数讲解

ibpcap&#xff08;Packet Capture Library&#xff09;&#xff0c;即数据包捕获函数库&#xff0c;是Unix/Linux平台下的网络数据包捕获函数库。它是一个独立于系统的用户层包捕获的API接口&#xff0c;为底层网络监测提供了一个可移植的框架。 一、libpcap工作原理 libpcap…

Linux常用命令(三)

man 查看帮助文档 alias ls : 查看命令是否被封装 echo &#xff1a; 显示字符串到屏幕终端 echo $PATH : 将环境变量打印出来 poweroff&#xff1a;关机 rebot&#xff1a;重启 需要管理员权限 vim是从vi发展过来的文本编辑器 命令模式&#xff1a;打开文件之后默认进入命令模…

浅谈iptables防SYN Flood攻击和CC攻击

何为syn flood攻击&#xff1a; SYN Flood是一种广为人知的DoS&#xff08;拒绝服务攻击&#xff09;是DDoS&#xff08;分布式拒绝服务攻击&#xff09;的方式之一&#xff0c;这是一种利用TCP协议缺陷&#xff0c;发送大量伪造的TCP连接请求&#xff0c;从而使得被攻击方资源…

Linux之静态库

命名规则&#xff1a; lib 库的名字 .a 制作步骤 生成对应.o文件 .c .o 将生成的.o文件打包 ar rcs 静态库的名字&#xff08;libMytest.a&#xff09; 生成的所有的.o 发布和使用静态库&#xff1a; 1&#xff09; 发布静态 2&#xff09; 头文件 文件如下图所示&…