前言

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. Hbase单点安装Version1.1.5

    Hbase单点安装,基于版本1.1.5, 使用hbase-1.1.5.tar.gz安装包. 1.安装说明 使用Hbase自带zookeeper和本地文件目录存储数据 2.安装规划 角色规划 IP/机器 ...

  2. Linux 安装并启用 PHP-FPM

    首先,在编译时带上 --enable-fpm 参数: [root@localhost local]# yum -y install libxml2 libxml2-devel gd gd-devel ...

  3. CS基础 float 浮动的使用方法

    html代码: <body> <div class='red'> </div> <div class='green'> </div> < ...

  4. slf4j+logback日志框架 的具体使用操作【spring boot自带的默认日志框架】

    1.前言 是不是还在使用System.out.println()打印数据到控制台看? 东西少还好,如果多起来,那就看的很烦人了,特别还有加时间等信息. 怎么解决? 可以使用日志框架 ,常见的有 log ...

  5. 【C】C语言大作业——学生学籍管理系统

    文章目录 学生管理系统 界面 主界面 登陆界面 注册界面 管理界面 学生界面 退出界面 链接 注意 学生管理系统 学C语言时写的一个大作业,弄了一个带图形界面的,使用的是VS配合EasyX图形库进行实 ...

  6. JVM探究(一)谈谈双亲委派机制和沙箱安全机制

    JVM探究 请你谈谈你对JVM的理解?java8虚拟机和之前的变化gengxin? 什么是OOM,什么是栈溢出StackOverFlowError JVM的常用调优参数有哪些? 内存快转如何抓取,怎么 ...

  7. 微服务架构 | 3.2 Alibaba Nacos 注册中心

    目录 前言 1. Nacos 基础知识 1.1 Nacos 命名方式 1.2 Nasoc 是什么 1.3 Nacos 的 4 个关键特性 1.4 Nacos 生态图 1.5 Nacos 架构图 1.6 ...

  8. 【SpringCloud-Alibaba】环境搭建以及注意事项

    一.开发环境 JDK 1.8 SpringBoot 2.1.7.RELEASE SpringCloud-Alibaba 2.1.2.RELEASE 数据库MySQL 5.8 如果需要修改版本请参照:S ...

  9. Android开发-资源导入

    安卓开发首先要导入开发资源,这些资源包括图片,图标等,方便开发过程中的使用 我是跟着b站博主做的记账本app所以导入的资源也来自于网络 将资源导入到res文件夹下这里面包括颜色资源,布局资源,图片资源 ...

  10. Zookeeper 源码解析-环境准备

    为了深入学习Zookeeper,准备把zookeeper源码导入eclipse中学习 一.Ant环境准备 因为我自己用的是Mac,直接输入命令:brew install ant即可 如果是window ...