TCP相关细节

1. 常用TCP参数

1.1 ReceiveBufferSize
ReceiveBuffersize指定了操作系统读缓冲区的大小, 默认值是8192(如图5-10 所示)。在第4章的例子中,会有"假设操作系统缓冲区的长度是8" 这样的描述,可通过socket.ReceiveBufferSize= 8 实现。当接收端缓冲区满了的时候,发送端会暂停发送数据,较大的缓冲区可以减少发送端暂停的概率, 提高发送效率

1.2 SendBufferSize
SendBuffersize 指定了操作系统写缓冲区的大小,默认值也是8192。对于那些没有处 理 好 “ 完整发送数据 ” 的网络模块 ( 见 4 . 5 节 ), 可以将SendBuffersize设成较大的值 , 以避免因发 送不完整而带来的各种问题 ( 图 5 - 1 0 )。 笔者见过有些还算成功的游戏项目 , 虽没有处理好数据的接收问题,但将 Sen dBuffer si ze 调大10倍,也能让游戏正常运转。

1.3 NoDelay
指定发送数据时是否使用Nagle 算法,对于实时性要求高的游戏,该值需要设置成 true Nagle 是一种节省网络流量的机制,默认情况下,TCP 会使用Nagle 算法去发送数据。
Nagle 算法的机制在于,如果发送端欲多次发送包含少量字节的数据包时,发送端不 会立马发送数据,而是积攒到了一定数量后再将其组成一个较大的数据包发送出去。
启用Nagle 算法可以提升网络传输效率,但它要收集到一定长度的数据后才会把它们 一 块儿发送出 去。这样一来,就 会降低网 络的实时性, 大部分实时网络游戏都会关闭 Nagle 算法,将socket.NoDelay 设置成true

1.4 TTL

TTL 指发送的IP数据包的生存时间值 (Time To Live , TTL ) 。 TTL 是 IP 头部的一 个值 ,
该值表示一个IP 数据报能够经过的最大的路由器跳数。发送数据时, TTL 默 认为64 (TTL 的默认值和操作系统有关,Windows
Xp默认值为128,Windows7默认值为64, Window10 默认值为6 5, Lin ux 默认值为 255 )。

数据在网络上传输, 实际上是经过多个路由器转发的。如图5- 13所示,发送端往接收端 发送一个卫数据报,初始的TTL
为64,在经过第一个理由器时,『头部的TTL减小,变成 63;
在经过第二个路由器时,变成了62。以此类推,直到TTL等于0,路由器就会丟弃数据。

在这里插入图片描述
在网络游戏中, 如果某些偏远地区用户时不时无法按收数据 , 可以尝试增大TTL值 ( socket.ttl=xxx)来解决问题。

1.5 ReuseAddress

Reuse Address 即端又复用 , 让同一个端又可被多个 socket 使用 。 一 般 情 况 下, 一 个 端 又只能由一个进程独占,假设服务端程序都绑定了1234端又,若开启两个服务端程序,虽 然, 第一个开启的程序能够成功绑定端又并监听,但第二个程序会提示“
端又己经在使用 中 ” , 无 法 绑 定 端 又。 在 计 算 机 中 , 退 出 程 序 与 释 放 端 又 并 不 同 步 。 在 5. 2 . 3 节 “ T C P 连 接 的终止〞 中,我们知道TCP断开连接会经历4次挥手。4次挥手需要时间,在网络不好的情况下,程序还会多次重试。当服务端程序崩溃,但它持有的Socket 不会被立马释放,这 时候重启 服务器就会遇到“ 端 又已经在使用中”的情形。等到Socket 被释放后(这个过程 可 能 要 十 几 分钟 时 间 ) , 服 务 端 才 能 成 功 重 启 。

对于人 气爆棚的大型网游, 十几分钟的等待时间会造成很大损失,一般要求在程序崩 溃 ( 尽 管 也 不 应 该 崩 溃, 但 人 算 不
如 天 算 ) 后 立 刻 重 启 , 继 续 提 供 服 务 。 端 又 复 用 最 常 见 的 用途是, 防止服务器 重启时,
之前鄉定的端又还未释放或者程序突然退出而系统没有释放 端 又。这种情况下如果设定了端又复用,则新启动的服务器进程可以直接鄉定端又。如果
没有设 定端又复用, 绑定会失败,提示端又己经在使用中,只好等十几分钟再重试了。 设 置 端又 复 用 使 用 s o c k e t 的
Sctsocket Option 方 法 , 代 码 如 下 所 示 。

Socket socket= new socket(AddressFamily.InterNetwork, socketrype.stream, ProtocolType.Tcp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

尽 管端又复用能解决服务端立即重启的问题,但它存在安全隐患。 主动关闭方有可能 在下次 使用时 收到上一次连接的数据包, 包括关闭连接响应包或者正常通信的数据包, 有可能出现奇怪现象

1.6 LingerState
LingerState 的功能是设置套接字保持连接的时间。

在这里插入图片描述
服务端中,会使用 下面的代码处理客户
端主动关闭连接,即在收到长度为0 的消息
后 , 调 用 clientfd.Close()关 闭 连 接 。
在这里插入图片描述
在这里插入图片描述
发送缓冲区还有尚末发送的数据, 那么直接调用Close 关闭连接,缓冲区中的数据将被丢弃。这种关闭方式很暴力,因为对端 可 能 还 需 要 这 些 数 据。 在 服 务 端 收 到 关 闭 信 号 后 , 有没有办法先把发送缓冲区中的数据发完,再关闭连接呢 ? LingerState 就是为了解决这个问题而诞生的 。

socket.LingerState = new LingerOption(true, 10);

其中的LingerOption 带有两个参数。第一个参数是LingerState.Enabled,代表是否启用 LingerState,只有设置为true 才能生效。第二个参数是LingerState.Linger Time,指定超时 时间。如果超时时间大于0 (比如10 秒),操作系统会尝试发送缓冲区中的数据,但如果网络状况不好,超过10秒还没有发完,它还是会强制关闭连接。
如果LingerState.LingerTime设置为0,系统会一直等到数据发完才关闭连接,无论等待多长时间。开启LingerOption能够在一定程度上保证发送数据的完整性。
在这里插入图片描述
服务端进入TIME_WAIT状态后,会等待一段时间再释放自由.对于高并发的服务端,过多的TIME_WAIT会占用系统资源,不是已经好事。有时候需要减小服务器的TIME_WAIT值,以求快速释放自由

2. Close的恰当时机

Lingerstate选项可以让程序在关闭连接前发完系统缓冲区中的数据,然而,这并不代表能将所有数据发出去。

下面完善代码使连接关闭时,依然能够完整发送数据。
对于主动关闭的一方(假设调用下述Close 方法关闭连接),应判断当前是否还有正在
发送的数据 。如有 , 只将标志位 isClosing 设置为 true , 等数据发送完再关闭连 接 ; 如果没有正在发送数据,直接调用socket.Close()关闭连接。代码如下:

bool isClosing = false;

//关闭连接
public void Close() {
    //还有数据在发送
    if(writeQueue.Count > 0) {
       isClosing = true;
    } else { //没有数据在发送
       socket.Close();
    }
}

由于设置了isClosing 标志位,在关闭连接的过程中,程序只负责将已有的数据发送 完,不会发送新的数据。可以在Send 方法中添加判断,假如程序处于Closing状态,不能发送信息。代码如下:

//点击发送按钮 
public void Send ( )
{
	if (isClosing) {
	   return;
	}
    // 拼接字节 , 省略组装 sendBytes 的代码
    byte[] sendBytes = 要发送的数据 ;
    ByteArray ba = new ByteArray (sendBytes);
    writeQueue.Enqueue (ba); 
    // send
    if(writeQueue.Count == 1){
        socket. BeginSend(ba.bytes, ba.readIdx, ba.length, 0, SendCallback, socket);
    }
}        

在BeginSend 回调两数中 , 还需要判断程序是否处于isClosing状 态, 如果程序发 送完写入队列的所有数据,而且处于isClosing 状态,应调用socket.Close 关闭连接。代码如下:

public void Sendcallback(IAsyncResult ar) {
    // 获取state、Endsend 的处理
    Socket socket = (Socket) ar.AsyncState; 
    int count = socket.EndSend(ar);
    // 判断是否发送完整
    ByteArray ba= writeQueue.First (); 
    ba.readIdx+=count;
    if(count ==ba.length){ 
       //发送完整
       writeQueue. Dequeue ( );
       ba = writeQueue.First ();
    }   

    if(ba != null){
        //发送不完整,或发送完整且存在第二条数据 
        socket. BeginSend(ba.bytes, ba.readIdx, ba.length,
0, SendCallback, socket);
     } else if(isClosing) {
           socket.Close ( );
     }
}

3. 心跳机制

断开连接时, 主动方会给对端发送 F I N 信 号 , 开启4 次挥手流程 。 但在某些情况下, 比如拿着手机进人没有信号的山区,更极端的,比如有人拿剪刀把网 线剪断。虽然断开了连 接 , 但主动方无法给对端发送 FIN 信号 ( 网线剪断了还能干什么? ), 对端会认为连接有效,一直占用系统资源。

游戏开发中,TCP默认的KeepAlive 机制很“ 鸡肋”,因为上述的“一段时间” 太长, 默认为2小时 。 一般会自行实现心跳机制 。心跳机制是指客户端定时 ( 比 如 每 隔 1 分 钟 ) 向 服务端发送P I N G 消 息 , 服 务 端 收 到 后 回 应 P O N G 消 息 。 服 务 端 会 记 录客 户 端 最 后 一 次 发 送 P I N G 消 息 的 时 间 , 如 果 很 久 没 有 收 到 (比 如 3 分 钟 ) , 就 假 定 连 接 不 通, 服 务 端 会 关 闭 连 接 , 释放系统资源

心跳机制也有缺点,比如在短暂的故障期间,它们可能引起一个良好连接被释放; PING和PONG消息占用了不必要的宽带; 在流量如黄金的移动网络中,会让玩家花贵更多 的流量费。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机的无人监守点滴控制系统设计

摘要 : 在当代社会 , 点滴是一种常用的诊疗方法 。 为了减轻医护人员的压力 , 设计了一种基于单片机的无人监守点滴控制系统, 该系统共由 2 个板子组成 , 其中一个主控板子 , 一个检测板子 。 检测板与…

《Windows API每日一练》4.2 设备环境

在第三章我们已经使用设备环境句柄在窗口客户区绘图了。在图形输出设备(比如屏幕或者打印机)上绘制图形,必须首先获取设备环境,即DC的句柄。当 Windows把这个句柄交给你的程序,Windows同时也就给予你使用这个设备的权限…

字节智能体平台:扣子原理和实践案例

完整内容: 字节智能体平台:扣子原理和实践案例

Day52 代码随想录打卡|二叉树篇---二叉搜索树中的众数

题目(leecode T501): 给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。 如果树中有不止一个众数&#xff0c…

什么是GPT-4

什么是GPT-4 ChatGPT 可以说,ChatGPT的发展,主要的分水岭在GPT-4,GPT-4主要是文本对话,且训练度也不够完善。GPT-4之后不但训练度得到了巨大提升,模型支持的参数量更是预计有1万亿参数,在这之后出现的GPT-4…

正运动邀您共聚2024深圳激光展,助力激光加工与智能制造!

■展会名称 2024深圳激光展 ■展会日期 2024年6月19日 - 21日 ■展馆地点 深圳国际会展中心(新馆) ■展位号 9H - D101 6月19至21日,深圳激光展将在中国深圳国际会展中心(新馆)举办。 激光加工在消费电子、光伏锂电新能源、半导体等行…

themleaf 页面弹层取值

themleaf 页面弹层取值 创作背景themleaf页面事件onbluronclick 页面参数提交 创作背景 个人在日常开发中,遇到了一个需求页面,页面交互较多,用到的事件也很丰富,特此记录,方便后续查找也方便有需要的开发者采用&…

shell文本三剑客 awk 和 grep

awk 前言 AWK是一种优良的文本处理工具。它不仅是 Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。 Linux中最常用的文本处理工具有grep,sed,awk。行内将之称为文本三剑客,就功能量和效率来看,awk是当之无愧的文本三…

代码随想录算法训练营day22|701.二叉搜索树中的插入操作、 450.删除二叉搜索树中的节点、 235. 二叉搜索树的最近公共祖先

701.二叉搜索树中的插入操作 这道题较为简单,只需要通过递归找到符合要求的叶子节点,并将节点插入即可。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(…

软件体系结构笔记(自用)

来自《软件体系结构原理、方法与实践(第三版)》清华大学出版社 张友生编著 1-8章12章 复习笔记 如有错误,欢迎指正!!!

【每日刷题】Day65

【每日刷题】Day65 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. LCR 175. 计算二叉树的深度 - 力扣(LeetCode) 2. 序列找数_牛客题霸_牛客网…

(新)Spring Security如何实现登录认证(实战篇)

一、回顾认证流程详解 概念速查: Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。 AuthenticationManager接口:定义了认证Authentication的方法 UserDetailsService接口:加载用户特定数据的核心接…

内网安全【2】-域防火墙

1.判断什么时候用代理 2.判断什么时候用隧道 3.判断出网和不出网协议 4.如何使用代理建立节点并连接 5.如何使用隧道技术封装协议上线 6.判断哪些代理或隧道情况选择放弃 代理技术:解决网络通讯不通的问题(利用跳板机建立节点后续操作)(网络设置导…

【C++】STL中stack、queue、deque的使用

前言:在前面我们学习了List的模拟实现与使用,今天我们进一步的来学习stack、queue、deque的使用方法,然后为后面的模拟实现做一下铺垫。 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:高质量&#xff…

S7-1200PLC和V90总线伺服通过工艺对象实现定位控制(标准报文3应用)

V90PN总线伺服驱动和S7-1200PLC通信需要安装GSD文件,PLC通过各种标准报文实现V90的位置和速度控制。 1、V90伺服驱动器控制(PN版本) V90伺服驱动器控制(PN版本)_v90 pn 最简接线-CSDN博客文章浏览阅读303次。V90伺服驱动器脉冲控制常用参数和接线,请查看下面文章链接:SMAR…

VirtFuzz:一款基于VirtIO的Linux内核模糊测试工具

关于VirtFuzz VirtFuzz是一款功能强大的Linux内核模糊测试工具,该工具使用LibAFL构建,可以利用VirtIO向目标设备的内核子系统提供输入测试用例,广大研究人员可以使用该工具测试Linux内核的安全性。 工具要求 1、Rust; 2、修补的Q…

学习cel-go了解一下通用表达语言评估是什么

文章目录 1. 前言2. cel-go2.1 cel-go关键概念Applications(应用)Compilation(编译)Expressions(表达式)Environment环境解析表达式的三个阶段 3. cel-go的使用4. cel-go使用5. 说明6. 小结7. 参考 1. 前言 最近因为在项目里面实现的一个使用和||来组合获取字段值的功能有点儿…

一键解锁创意无界:高效AI生成古典肖像图片,轻松打造艺术化身

在数字化时代,创意与艺术的结合正逐渐改变我们的生活。你是否曾梦想过拥有一幅专属于自己的古典肖像画,却又苦于找不到合适的画师或高昂的费用而望而却步?现在,这一切都将成为现实! 进入首助编辑高手的AI魔法智绘图板块…

Java—装饰器模式

介绍 装饰器模式 装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地将行为添加到现有的对象中,而无需修改其代码。装饰器模式提供了比继承更灵活的功能扩展方式。 主要角色 Component:定义一个对…

【编程技巧】降低程序复杂度:控制逻辑与业务逻辑分离

为什么要降低代码复杂度 好的项目都是迭代出来的,所以代码肯定是会被人维护的 降低代码复杂度就是为了降低下一个维护人的维护成本,更简单地理解跟修改代码 代码组成 代码逻辑 控制逻辑 业务逻辑 控制逻辑 控制业务逻辑的代码 例如:加缓存…