关于socket编程

沙摩柯
• 阅读 3257

EAGAIN错误

linux/unix下读写socket时可能发生EAGAIN错误,比如在非阻塞(non-block)的情况下,客户端给服务器发送了一个空字符,事件接收到消息连接会让服务器会去读,但是没有数据可读,会发生错误:

EAGAIN : Resource temporarily unavailable

因为是异步的立马返回了,又没有读到数据所以会提示EAGAIN,提示当前不可读稍后重试。其它的比如文件操作或者fork失败等也会产生该错误。
windows上,EAGAIN的名字叫做EWOULDBLOCK,在使用非阻塞套接字进行异步编程时,需要通过errno对这些情况作出处理

各层传输长度约束

MTU,最大传输单元,链路层的最大长度,通常为1500字节
IP包,包头中以16位数来描述其长度,最大为65535字节
当IP包大小超过了MTU值,就需要进行分片,然后在客户端进行重组。但不同网络的MTU值可能不同,会导致数据包被再次分片。若将IP包设置为不允许分片(分片会降低性能),当某一网络的MTU值比发送时的MTU值要小,则数据包将被丢弃,发送方会收到ICMP消息,通知其需要进行分片。这个最小的MTU称为路径MTU

MSS,最大分段大小,表示TCP传往另一端的最大数据的长度,其值越大,一次传输的数据越多。
MSS = MTU - IP头长度 - TCP头长度, 通常为1460 = 1500 - 20 - 20。
建立TCP连接的两端在三次握手时会协商MSS的大小,一方发出syn报文时会带上mss大小,另一方应答时也是如此。双方会选择较小的mss作为发送tcp分片的大小。

socket缓冲区

默认大小为1024*8 = 8096个字节,默认是socket先将数据发送到系统缓冲区,也就是8096bytes的地方,之后接收函数再从系统缓冲区拷贝数据到socket缓冲区,发送出去。若经常很快将缓冲区写满,可以将缓冲区的设置大一些,使用setsockopt函数
使用缓冲区设置的目的是减少网络IO,这点很重要。不用缓冲区,数据立即发送,网络忙的时候更易出错。

缓冲区的拷贝,send时也称为应用缓冲区拷贝到发送缓冲区,新拷贝到发送缓冲区的数据会由系统来发送,注意并不是立刻就由系统发送了,系统会自行处理,可近似看作立即发送。发送缓冲区中的数据,发送后在得到对端ack响应前不会删除。

Nagle算法

默认情况下,数据发送使用Nagle算法,其要求在任何时刻最多只能有一个未被确认的数据块
Nagle算法的规则:

  1. 如果包长度达到MSS,则允许发送

  2. 如果该包含有FIN,则允许发送

  3. 设置了TCP_NODELAY选项,则允许发送

  4. 未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送

  5. 上述条件都未满足,但发生了超时(一般为200ms),则立即发送

算法的上的很明确,避免向网络中发送过多的小包,先行等待200ms左右,如果上一个包的ACK仍然没有收到或是包长度仍然未达到MSS才继续发包,这样可以提高网络吞吐量,但降低了实时性,可以通过设置TCP_NODELAY来禁用Nagle算法

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
3年前
java通过ServerSocket与Socket实现通信
首先说一下ServerSocket与Socket.1.ServerSocketServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态.ServetSocket有三个构造方法:(1)ServerSocket(intport);这个使用指定的端口
Wesley13 Wesley13
3年前
javaNIO编程
UnblockingIO(NewIO):同步非阻塞的编程方式NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题,NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。也就是说,这个时候,已经不是一个连接就要对应
雷厉风行 雷厉风行
2年前
mac软件-G-dis for Mac(Redis客户端)v7.0.2激活版
Mac好用的Redis客户端Gdis破解版推荐给大家,Gdis是采用纯swift语言开发的,底层采用swift的socket编程,通过调用poll、MSGPEEK来控制socket连接超时和做socket阻塞判断。支持二进制的key、value数据存入和取
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
Java Socket编程——通信是这样炼成的
Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket。像大家熟悉的QQ、MSN都使用了Socket相关的技术。下面就让我们一起揭开Socket的神秘面纱。Socket编程一、网络基础知识(参考计算机网络)关于计算机网络部分可以参
Stella981 Stella981
3年前
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法参考文章:(1)Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.codeprj.com%2Fblo
Stella981 Stella981
3年前
Spring Boot+Socket实现与html页面的长连接,客户端给服务器端发消息,服务器给客户端轮询发送消息,附案例源码
功能介绍1.客户端给所有在线用户发送消息2.客户端给指定在线用户发送消息3.服务器给客户端发送消息(轮询方式)注意:socket只是实现一些简单的功能,具体的还需根据自身情况,代码稍微改造下项目搭建项目结构图!(https://img2020.cnblogs.com/blog/15044
Stella981 Stella981
3年前
Socket心跳机制
本文是我在实际工作中用到的Socket通信,关于心跳机制的维护方式,特意总结了一下,希望对朋友们有所帮助。Socket应用:首先Socket封装了tcp协议的,通过长连接的方式来与服务器通信,是由服务器和客户端两部分组成的,当客户端成功连接之后,服务器会记录这个用户,并为它分配资源,当客户端断开连接后,服务器会自动释放资源。但在实际的网络环