errno

errno不应该理解为错误原因,应该理解为调用函数失败的原因。

连接:

1.accept返回-1

accept返回-1表示获取tcp全连接队列中的连接的时候失败,会对errno进行设置:

errno == EWOULDBLOCK 表示全连接队列为空,这个在阻塞IO中见不到,在非阻塞IO中会见到

2.linux中全连接队列的大小设置

这个是在listen的时候由传入的backlog参数指定,mac系统的话backlog指定的是半连接队列和全连接队列对的总和。

3.connect返回-1

errno == EINPROGRESS 表示正在建立连接

errno == EISCONN 连接已经建立

上面的异常一般发生在非阻塞套接字,阻塞情况的话除非是服务器IP:port设置不对就根本连不上,阻塞套接字的connect的话他是一直等待TCP三次握手完成,可以进行数据交互的时候进行返回;

非阻塞的话由于connect过程中要实现TCP的三次握手,因此connect之后直接返回一般情况下返回-1,也就是正在进行连接的状态,可以检测描述符的写事件,如果可写那么说明连接建立完毕(不能检测可读,因为可读的话需要对端发送数据过来才检测的到)。

断开:

TCP是支持全双工的通讯方式,他同时也允许半连接的通讯,就是说只进行单方向的连接;

主动断开:

close(fd)

shutdown(fd, SHUT_RDWR)

shutdown(fd, SHUT_RD) -- 主动关闭本地读端,对端写端关闭

shutdown(fd, SHUT_WR) -- 主动关闭本地写端,对端读端关闭

被动断开:

read读取到0 -- 检测到本地读端关闭

write == -1 && errno == EPIPE -- 检测到本地写端关闭

消息到达

TCP的连接是在内核中完成的,即使服务器端没有进行accept,客户端也可以进行数据发送,这些数据会缓冲在内核的数据缓冲区中。

那么当内核缓冲区满了会怎么样呢?是会客户端数据发送阻塞?还是客户端依旧在发送,发送过去的数据会被服务器端丢弃?

在使用阻塞式套接字进行测试发现是客户端数据会阻塞发送,直到接收端读取数据后发送端确认对方收到后继续进行数据发送。

read返回-1

errno == EWOULDBLOCK -- 读缓冲区为空,非阻塞读取

errno == EINTR -- 被信号打断,阻塞读取

其他错误 -- 需要close掉

write返回-1

errno == EWOULDBLOCK -- 写缓冲区满了,非阻塞读取

errno == EINTR -- 被信号打断,阻塞读取

阻塞IO和非阻塞IO

阻塞与非阻塞操作取决于对应描述符是阻塞的还是非阻塞的

两者区别在于当遇到无法立即执行的情况时的应对方式,即是否阻塞;而在进行相应操作的时候,比如读取从内核数据的过程中或者写入内核用户区数据的过程中,这个过程不论文件描述符是否设置为非阻塞他都是阻塞执行的。

文件描述符默认是阻塞的,通过fcntl可以设置为非阻塞:

int flag = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flag | O_NONBLOCK);

IO多路复用

就是使用一个接口检测多个描述符状态,如select、poll、epoll;在检测到满足条件的时候,就进行返回,然后用户根据返回数据对目标文件描述符进行操作。

epoll

epoll_create -- 内核中创建epoll红黑树和epoll就绪队列

epoll_ctl -- 针对红黑树进行检测事件操作,如添加、修改和删除。

epoll_wait -- 在内核检测到条件满足的时候,将满足条件的事件链接到双向链表中(内核红黑树节点数据结构增加两个指针即可),然后返回的时候将对应的数据复制到传入epoll_wait的数组中。

epoll_event -- 这个数据中的data域如果作为指针使用,那么该指针的意义是指向用户区某片空间的指针,data数据仅用于绑定和对应文件描述符自定义的数据。

nginx使用epoll的边缘触发 -- 为了节省发送数据过程中对发送的内核控制(水平触发下会一直触发写可用);

多线程的意义:多线程的意义和目的就是为了更加高效的使用CPU,在线程A进行IO阻塞的时候切换到线程B进行运行。多核CPU的话,多线程可以提升程序的运行效率;

关于backlog

阻塞模式下,如果连接超过了backlog,那么新的连接到达的时候会被阻塞,经过一段时间返回失败 -- "Connection timed out"

关于send和write

send和recv针对的过程是用户区数据和内核区数据,send将用户区数据复制到内核区,recv是将内核区数据复制到用户区;他和实际的网络层数据收发没有关系,网络层的数据交互是由内核实现的。

延迟ACK -- 通过setsockopt可关闭

ACK会在接收到数据包之后延迟一段时间进行发送,如果在此过程中多个数据包到达,会不断重置ACK计时,超时后会根据接收到的数据包进行ack回应。

状态转换

close的时候发送缓冲区还有数据

这种情况下与套接字的SO_LINGER属性相关,默认的情况就是连接会发送完毕发送缓冲区中的数据,最后才发送FIN包。

close_wait大量存在

伴随着close_wait状态大量存在的时候,必定伴随着对端fin_wait_2大量存在,这个的本质就是close_wait端没有及时的close掉套接字导致四次挥手卡在了该状态。可以先close掉,或者将close之前的操作通过线程处理,中止就是尽快close掉套接字描述符。

fin_wait_1状态下会进行重发,tcp_orphan_retries是对应的次数设置,超过该次数会直接close掉;

fin_wait_2状态,该状态需要对端close才能进入time_wait状态,如果对端不发,他就一直在该状态,可以通过开启tcp的keep-alive在超时时使fin_wait_2关闭。

last_ack状态会在重发多次后如果一直收不到ack,就直接进入close状态。

close之后,文件描述符资源释放,在套接字连接进入close状态之后,tcb资源才被释放(读、写缓冲在确认连接断开后同时释放)。

如果希望在time_wait阶段就使用对应的端口,可以使用端口复用进行对端口进行使用。

夹带私货:

tcp个人理解就是udp的升级版本,由于tcp是直接在内核中实现了,所有更新较慢,kcp可以理解为用户层的tcp,就是将tcp的种种特性基于udp进行用户态编程实现,从而修改所有有关可靠连接的属性设置。

关于TCP使用上的一些总结相关推荐

  1. “在 TCP 网络上检测出有重复名称”错误的解决方法

    "在 TCP 网络上检测出有重复名称"错误的解决方法 主要问题:在 TCP 网络上检测出有重复名称. 发送消息的计算机的 IP 地址在数据中. 请在命令窗口中使用 nbtstat ...

  2. 双网卡“在 TCP 网络上检测出有重复名称”错误

    NetBT检测重复名称错误解决方法: "在 TCP 网络上检测出有重复名称"错误的解决方法 主要问题:在 TCP 网络上检测出有重复名称. 发送消息的计算机的 IP 地址在数据中. ...

  3. TCP文件上传Java_java 基于TCP协议的文件上传

    参考文档 1.https://www.sxt.cn/Java_jQuery_in_action/ten-filebytestream.html 2.https://www.sxt.cn/Java_jQ ...

  4. 用java网络编程中的TCP方式上传文本文件及出现的小问题

    自己今天刚学java网络编程中的TCP传输,要用TCP传输文件时,自己也是遇到了一些问题,抽空把它整理了一下,供自己以后参考使用. 首先在这个程序中,我用一个客户端,一个服务端,从客户端上传一个文本文 ...

  5. Jmeter TCP 取样器 上一个请求响应结果参数传个下一个请求,响应结果为空

    出现的问题,上一个请求成功,但是下一个请求返回参数是200 ,但是响应结果为空,如图.原因是因为我没有勾选close connection 每个请求结束后关闭连接. 先来了解一下TCP 取样器界面的的 ...

  6. TCP|Android上TCP通信实现

    版权声明:本文出自朋永的博客,转载必须注明出处. https://blog.csdn.net/VNanyesheshou/article/details/74896575 转载请注明出处:http:/ ...

  7. 关于JAVA网络编程UDP和TCP(上)

    对于JAVA的网络编程我们又称之为socket编程.首先,网络编程,顾名思义,要涉及到网络,其中网络协议是必不可少的对于我们而言,一个重要的网络协议是大家要会的:TCP/IP协议,udp协议. 一.网 ...

  8. nmblookup - 基于TCP/IP上的NetBIOS客户用于查询NetBIOS名字的程序

    总览 SYNOPSIS nmblookup [-M] [-R] [-S] [-r] [-A] [-h] [-B <broadcast address>] [-U <unicast a ...

  9. 网络体系结构OSl/TCP(本质上是快递运输过程)

    先讲国际开放系统互联参考模型(一共七层) 这七层其实就是快递公司的七大部门,每个部门都各自管理快递从发件地到目的地,运输过程负责所履行不同部门间的协同工作. 如应用部门(应用层),该部门更像是快递点, ...

最新文章

  1. 元宇宙中可跨语种交流,Meta 发布新语音模型,支持128种语言无障碍对话
  2. 聊聊Service Mesh:linkerd
  3. Neural Representation Learning in NLP | 实录·PhD Talk #07
  4. Google学术发布2019年最有影响力的7篇论文(附下载链接)
  5. PHP工程师面临的成长瓶颈
  6. mysql五种日期函数
  7. SpringSecurity分布式整合之资源服务器搭建和测试
  8. Linq中string转int的方法
  9. 优化if-else代码的八种方案
  10. 服务注册发现方案需求调研
  11. 巴斯勒相机外部触发接线_2021新疆欧姆龙相机回收童嫂无欺
  12. Java Threads -- 数据同步(1)
  13. 机器学习实战 11- SVD
  14. Word2003及Excel2003打开速度慢,如何解决?
  15. c语言中学生信息管理系统中删除学生信息,学生信息管理系统C语言编程
  16. 【JS中innerHeight/Width、clientHeight/Width和offsetHeight/Width使用及其详解】
  17. Java集成openCV实现图片背景切换
  18. 怎么用spss做冗余分析_SPSS进行典型相关分析结果总结
  19. html5鲜花网页代码,JS制作漂亮的鲜花完整代码
  20. 天融信java面试_天融信面试准备

热门文章

  1. matlab中绘制牟合方盖,牟合方盖 - calculus的日志 - 网易博客
  2. 云服务器部署和安装开源笔记leanote完整教程
  3. Arduino遍历字符串
  4. hover事件导致闪烁问题
  5. 当代大学生想进入IT行业,要做好哪些准备呢?
  6. 【Python基础学习笔记day05】pycharm注释的作用+单行注释(行注释)+多行注释(块注释)+关于代码规范
  7. 【每日一练】Ajax小案例-水果列表
  8. Linux 下Oracle中文乱码
  9. 安防运营服务市场现状及所遇问题的解决
  10. ZYNQ_Standalone_SD卡读写与性能测试