前言

tcp的包的格式可以看我以前的计算机网络整理,下面这些周边只是为了开发时候我们能用到一些理论知识。

正文

首先要介绍的就是域名,为啥有域名这东西呢?单纯站在网络的角度上讲这属于应用层的东西了。

如果站在万物互联的角度上讲,把互联网看做是一台大型电脑的话,那么域名就相当于句柄了。

句柄这东西解释一下,句柄(Handle)是一个是用来标识对象或者项目的标识符,可以用来描述窗体、文件等,值得注意的是句柄不能是常量。

Windows之所以要设立句柄,根本上源于内存管理机制的问题,即虚拟地址。简而言之数据的地址需要变动,变动以后就需要有人来记录、管理变动,因此系统用句柄来记载数据地址的变更。在程序设计中,句柄是一种特殊的智能指针,当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄

比如我们要访问某个服务,但是服务器的ip地址是可以变动的,那么如果是这样的话,那么就有一个问题,那就是这个ip要一直属于你,但是这是不可能的。

那么就有了域名这东西,ip再怎么变化,同一个域名代表着某种服务,域名不变服务就不变了。

那么我们知道源计算机到目标计算机的是通过ip协议的,也就是说传输跟域名是无关的,那么域名如何应对变化的ip呢?

那么就有人想出了DNS这东西,Domain name system(域名系统),它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。

大概是这么一个东西,使用的是udp,那么我们浏览器访问域名,实际上内部会帮助我们将域名转换为ip然后发送出去,那么域名标志就在我们应用层才知道是啥,比如说http将域名放在header 里面的host位置上。

上面是dns抓包。这里可以看到我配置了DNS 服务配置是192.168.0.1,也就是我的网关。

那么如果192.168.0.1 如果无法解析出域名,那么就会传到下一级DNS服务器了。

static void Main(string[] args)
{
var addresses = Dns.GetHostEntry("www.baidu.com").AddressList;
foreach (var item in addresses)
{
Console.WriteLine($"ip地址:{item.ToString()}");
}
Console.ReadLine();
}

我们代码中获取也是相当简单。

然后这里可以看到,我们一个域名会返回AddressList,也就是多个地址。

这个是一个常规现象,怎么说呢,可能多个ip配置一个域名,可以做到负载均衡的作用。

那么多个ip配置一个域名,那么访问域名访问的是哪个ip呢?

在域名解析过程中,通过层层解析,必将域名对应到 IP(逐级授权、中间 CNAME 层层转发,此处按下不表)对于对应到的IP,可能1个,也可能13个(不建议超过13个),DNS 会一股脑将这(些)个 IP 给解析客户端(如浏览器、操作系统的解析服务)最终的应用或系统解析服务,从中随机挑选一个(如果是定制的应用,还可以通过后续的应用层访问对获取到的 IP 做 HA 或权重)

也就是说你用哪个ip是应用程序自己决定的,当然有些库是帮你轮询了,也有些库只选用第一个,但这不是DNS帮你干的事情,DNS 只会返回你在服务商配置的信息。

一些大型网站或CDN服务商为了实现负载均衡,他们的DNS服务器会动态改变多个IP地址的顺序,使得每个IP地址都有机会成为解析结果中的第一个IP地址。

既然域名能解析成ip,那么ip是否能反向解析为域名呢?也是可以的。

https://baike.baidu.com/item/域名反向解析/9327917

平时也没过反向解析这东西,上面也是写道是邮件识别安全问题,不做过多的评论,总之是可以的。

那么对于我们的应用来说,现在ip修改的问题解决了,那么是否直接一个socket,然后通信编写我们自己的应用协议就行呢?

因为我们的应用各不相同,那么就有不同的场景,也就有了不同的需求,那么可以通过对socket的配置来满足我们的需求。

static void Main(string[] args)
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.ReceiveBuffer, 4098*2);
}

比如tcp是流,我们可以设置输入缓冲区的大小,当然也可以设置输出缓冲区的大小了。

但是值得注意的是,这个设置操作系统可能并不会100%执行,比如说我设置了两倍,那么操作系统不一定按照两倍,可能是1点多倍,这个操作系统有自己的算法的。

那么是否配置是否只影响性能呢?答案其实不是的,还可能短时间无法重启问题。

这就是著名的 time-wait 问题。

这上面标红的部分就是time-wait。

为啥有time-wait呢? time-wait 一定是在首先发送断开的一方。

下面把首先发送端口的比作是A,后面断开的比作是B。

为什么有time-wait呢? 因为A断开的一方没有time-wait,也就是说发送最后的ack这个socket销毁了,那么可能发送的ack没有到达B(丢失)。B就不知道A收到了FIN信号,那么B就会进行重试,但是A的socket消失了,然后B永远收不到Ack,无法正常关闭。

那么这个time-wait有什么问题呢? 比如我们的服务应用宕机了,如果socket 在time-wait 那么我们指定socket bind 某个指定的端口了,那么如果该socket处于time-wait状态,那么服务重启就会报告被端口占用情况。

那么有没有办法解决呢?

这个是允许绑定time-wait socket使用的端口。

Q:编写 TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?

A:这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。

前面几篇文章中提及到nagle这个词,nagle 是一个算法,主要是优化小数据网络流量问题。

nagle 是在什么条件下诞生的呢? 我们指定tcp 是建立在ip协议的基础上,ip协议和tcp协议都是占用字节的,如果你传输一个字节就要给你发送一次的话,也就是说协议的大小要大于数据的大小,那么可以想象流量多么浪费。

那么nagle 就是这样的,比如要发送nagle,n、a、g、l,这个一个字节一个字节发送的话,那么首先n传入到缓存中去,然后发送,这个时候等n传输的ack回来后,那么此时缓存中可能就有了agl,那么就会把agl全部发送出去。

也就是说要等上一个消息的ack确定对方收到后,才开始发送下一条消息。如果设置socket 为TCP_NODELAY为true,那么不会等上一个ack收到就会发送新的数据。

那么nagle 算法是不是百分百适用呢? 答案肯定是否定的,没有任何一种算法是100%的。

如果我们在传输大文件的时候,很快就会填充掉io的缓存,如果使用nagle 算法,那么要等待ack回来后才能发送,就有点影响效率了。

Nagle算法的规则(可参考tcp_output.c文件里tcp_nagle_check函数注释):

(1)如果包长度达到MSS,则允许发送;

(2)如果该包含有FIN,则允许发送;

(3)设置了TCP_NODELAY选项,则允许发送;

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

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

那么可能就有人问了,那么tcp 都没有ack确认后再进行发送,那么对方收到的包的顺序不就是乱的啊,怎么能保证数据流顺序正常呢?

这个问题的其实吧,tcp 的包里面的数据是有编号的,并不是说发送方发完消息,然后发送方收到了接收方收到了消息(ack),然后保证数据顺序的。

那这就太局限了,其实tcp保证顺序是有编号的,这就要从tcp格式说起了,以前整理的也有,后面再次整理的时候会补充。

socket的配置还有很多,比如TCP_CORK啊,可以百度看看。

上面就是为了说明一下tcp是一个非常复杂的协议, 我们在做应用的时候需要了解一些配置,或许有利于性能以及稳定性。下一节,多进程的tcp服务。

计算机网络再次整理————tcp周边[八]的更多相关文章

  1. 计算机网络再次整理————tcp的关闭[七]

    前言 tcp的关闭不是简单粗暴的,相对而言是友好优雅的,好聚好散吧. 那么友好的关闭方式是这样的: 假设这里是客户端请求关闭的,服务端倒过来. 客户端:我要请求关闭 服务端:我接收到你的请求了,等我把 ...

  2. 计算机网络再次整理————tcp例子第二前奏[四]

    前言 前文我们介绍了网络协议的各层,同时也介绍了一下我们在编写代码时候的服务端的accept.bind.listen.connect.send做了什么. 可以说是从宏观的角度,或者代码开发的角度来说的 ...

  3. 计算机网络再次整理————tcp例子[五]

    前言 本文介绍一些tcp的例子,然后不断完善一下. 正文 服务端: // See https://aka.ms/new-console-template for more information us ...

  4. 计算机网络再次整理————tcp[二]

    前言 本文不会去介绍tcp的具体协议,因为这个tcp 应该不能说是单纯的连接和传输数据这么简单,里面还有很多机制. 正文 首先介绍一下什么是协议族(protocal Family),举个例子PF_IN ...

  5. 计算机网络再次整理————tcp例子前奏[三]

    前言 简单编写一下tcp例子. 正文 我们常说IOS有7层,实际上也只有4层,或者这样说简单的说是4层. 首先是数据链路层,首先这一层解决了什么问题呢?为什么要有这一层呢? 首先要抛开有操作系统的意识 ...

  6. 计算机网络再次整理————socket[一]

    前言 以前也整理过吧,写了几篇之后,感觉没啥整理的必要了然后就放弃了,最近又想整理一下. 正文 这篇对应的是:https://www.cnblogs.com/aoximin/p/12235333.ht ...

  7. 计算机网络再次整理————UDP例子[六]

    前言 简单的说,UDP 没有 TCP 用的广泛,但是还有很多是基于UDP的程序的,故而简单介绍一下. 正文 秉承节约脑容量的问题,只做简单的介绍和例子,因为自己几乎也没怎么用过UDP. 只是了解和知晓 ...

  8. 计算机网络基础之TCP/IP 协议栈

    计算机网络基础之TCP/IP 协议栈 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.TCP/IP 协议栈概述 1>.什么是TCP/IP协议栈 Transmission C ...

  9. 计算机网络知识(TCP连接,TCP/UDP区别,HTTP与HTTPS,Socket原理等等)

    1.网络七层协议包含,物理层.数据链路层.网络层(ip协议).传输层(TCP传输控制协议.UDP用户数据报协议).会话层.表示层.应用层(http协议).是一个提供的概念架构协议. 2.TCP/IP协 ...

随机推荐

  1. Selenium_单选框和复选框的选中状态判定以及元素是否可用和可见判定(10)

    简单写个单选框和复选框界面 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /&g ...

  2. centos7 安装locate

    使用locate my.cnf命令可以列出所有的my.cnf文件 yum  -y install mlocate 原因是安装完后没有更新库 更新库:updatedb

  3. 手机访问web网页,使得显示自适应

    //禁止浏览器伸缩<meta name="viewport" content="user-scalable=0">//手机访问web网页,使得显示自 ...

  4. Linux上天之路系列目录

    Linux上天之路系列目录 Linux上天之路(一)之Linux前世今生 Linux上天之路(二)之Linux安装 Linux上天之路(三)之Linux系统目录 Linux上天之路(四)之Linux界 ...

  5. vue3.0+vite+ts项目搭建-分环境打包(四)

    分环境打包配置 新建.env.dev(或者.env) VITE_NODE_ENV = 'dev' VITE_HOST = 'http://local.host.com' 执行yarn dev ,控制台 ...

  6. synchronized学习笔记

    概述 我们都知道加锁的目的就是:序列化访问临界资源,即同一时刻只能有一个线程访问临界资源(同步互斥访问).在java对象中,每一个对象有且只有一个同步锁.这也意味着,同步锁依赖于对象而存在,当我们访问 ...

  7. 【Java】静态与非静态

    文章目录 静态与非静态 static关键字 使用static修饰属性:静态变量(或类变量) 类变量与实例变量的内存解析 使用static修饰方法:静态方法 使用static的注意点 开发中,如何确定一 ...

  8. 【Java】回形数

    回形数 键盘读入一个整数n(1-20),以n为矩阵大小,把1,2,3,4,5-按顺时针螺旋的形式填入. import java.util.Scanner; public class HuiXingSh ...

  9. 【reverse】逆向7 堆栈图

    [reverse]逆向7 堆栈图 前言 本章就是开始画堆栈图来打基础拉,堆栈熟悉了之后就可以开始C语言的逆向了. 这一章使用的exe文件,我已经上传到了我的个人网盘中,点击下载 1.准备工作 先看这张 ...

  10. C# 实现NPOI的Excel导出

    技术点: 1.自定义attribute属性 2.通过反射取类及其属性的attribute属性值 3.NPOI包常用属性及方法(我也仅仅知道用到过的,陌生的要么见名知意,要么百度查) 实现功能点: Li ...