关于网络编程的3个问题

一、TCP 和 UDP 可以同时绑定相同的端口吗?

答案:可以的

在数据链路层中,通过 MAC 地址来寻找局域网中的主机。在网络层中,通过 IP 地址来寻找网络中互连的主机或路由器。在传输层中,需要通过端口进行寻址,来识别同一计算机中同时通信的不同应用程序

所以,传输层的「端口号」的作用,是为了区分同一个主机上不同应用程序的数据包。

传输层有两个传输协议分别是 TCP 和 UDP,在内核中是两个完全独立的软件模块。

当主机收到数据包后,可以在 IP 包头的「协议号」字段知道该数据包是 TCP/UDP,所以可以根据这个信息确定送给哪个模块(TCP/UDP)处理,送给 TCP/UDP 模块的报文根据「端口号」确定送给哪个应用程序处理。

可以看到,数据的传输是一个五元组(源地址,目标地址,源端口号,目标端口号,数据传输协议),所以说可以同时监听一个端口号。

因此, TCP/UDP 各自的端口号也相互独立,如 TCP 有一个 80 号端口,UDP 也可以有一个 80 号端口,二者并不冲突。

二、多个 TCP 服务进程可以绑定同一个端口吗?

可以,需要在创建socket时,设置SO_REUSEADDR

还是以前面的 TCP 服务端程序作为例子,启动两个同时绑定同一个端口的 TCP 服务进程。

运行第一个 TCP 服务进程之后,netstat 命令可以查看,8888 端口已经被一个 TCP 服务进程绑定并监听了,如下图:

接着,运行第二个 TCP 服务进程的时候,就报错了“Address already in use”。

我上面的测试案例是两个 TCP 服务进程同时绑定地址和端口是:0.0.0.0 地址和8888端口,所以才出现的错误。

如果两个 TCP 服务进程绑定的 IP 地址不同,而端口相同的话,也是可以绑定成功的。

所以,默认情况下,针对「多个 TCP 服务进程可以绑定同一个端口吗?」这个问题的答案是:如果两个 TCP 服务进程同时绑定的 IP 地址和端口都相同,那么执行 bind() 时候就会出错,错误是“Address already in use”。

注意,如果 TCP 服务进程 A 绑定的地址是 0.0.0.0 和端口 8888,而如果 TCP 服务进程 B 绑定的地址是 192.168.1.100 地址(或者其他地址)和端口 8888,那么执行 bind() 时候也会出错。

这是因为 0.0.0.0 地址比较特殊,代表任意地址,意味着绑定了 0.0.0.0 地址,相当于把主机上的所有 IP 地址都绑定了。

重启 TCP 服务进程时,为什么会有“Address in use”的报错信息?

TCP 服务进程需要绑定一个 IP 地址和一个端口,然后就监听在这个地址和端口上,等待客户端连接的到来。然而在实践中,我们可能会经常碰到一个问题,当 TCP 服务进程重启之后,总是碰到“Address in use”的报错信息,TCP 服务进程不能很快地重启,而是要过一会才能重启成功。

这是为什么呢?

当我们重启 TCP 服务进程的时候,意味着通过服务器端发起了关闭连接操作,于是就会经过四次挥手,而对于主动关闭方,会在 TIME_WAIT 这个状态里停留一段时间,这个时间大约为 2MSL。

当 TCP 服务进程重启时,服务端会出现 TIME_WAIT 状态的连接,TIME_WAIT 状态的连接使用的 IP+PORT 仍然被认为是一个有效的 IP+PORT 组合,相同机器上不能够在该 IP+PORT 组合上进行绑定,那么执行 bind() 函数的时候,就会返回了 Address already in use 的错误

而等 TIME_WAIT 状态的连接结束后,重启 TCP 服务进程就能成功。

重启 TCP 服务进程时,如何避免“Address in use”的报错信息?

我们可以在调用 bind 前,对 socket 设置 SO_REUSEADDR 属性,可以解决这个问题。

int on = 1;

setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

因为 SO_REUSEADDR 作用是:如果当前启动进程绑定的 IP+PORT 与处于TIME_WAIT 状态的连接占用的 IP+PORT 存在冲突,但是新启动的进程使用了 SO_REUSEADDR 选项,那么该进程就可以绑定成功。

举个例子,服务端有个监听 0.0.0.0 地址和 8888 端口的 TCP 服务进程。‍

有个客户端(IP地址:192.168.1.100)已经和服务端(IP 地址:172.19.11.200)建立了 TCP 连接,那么在 TCP 服务进程重启时,服务端会与客户端经历四次挥手,服务端的 TCP 连接会短暂处于 TIME_WAIT 状态:

客户端地址:端口           服务端地址:端口        TCP 连接状态

192.168.1.100:37272          172.19.11.200:8888    TIME_WAIT

如果 TCP 服务进程没有对 socket 设置 SO_REUSEADDR 属性,那么在重启时,由于存在一个和绑定 IP+PORT 一样的 TIME_WAIT 状态的连接,那么在执行 bind() 函数的时候,就会返回了 Address already in use 的错误。

如果 TCP 服务进程对 socket 设置 SO_REUSEADDR 属性了,那么在重启时,即使存在一个和绑定 IP+PORT 一样的 TIME_WAIT 状态的连接,依然可以正常绑定成功,因此可以正常重启成功。

因此,在所有 TCP 服务器程序中,调用 bind 之前最好对 socket 设置 SO_REUSEADDR 属性,这不会产生危害,相反,它会帮助我们在很快时间内重启服务端程序。‍

前面我提到过这个问题:如果 TCP 服务进程 A 绑定的地址是 0.0.0.0 和端口 8888,而如果 TCP 服务进程 B 绑定的地址是 192.168.1.100 地址(或者其他地址)和端口 8888,那么执行 bind() 时候也会出错。

这个问题也可以由 SO_REUSEADDR 解决,因为它的另外一个作用是:绑定的 IP地址 + 端口时,只要 IP 地址不是正好(exactly)相同,那么允许绑定。

比如,0.0.0.0:8888 和192.168.1.100:8888,虽然逻辑意义上前者包含了后者,但是 0.0.0.0 泛指所有本地 IP,而 192.168.1.100 特指某一IP,两者并不是完全相同,所以在对 socket 设置 SO_REUSEADDR 属性后,那么执行 bind() 时候就会绑定成功。

PS:如果想多个进程绑定相同的 IP 地址和端口,也是有办法的,就是对 socket 设置 SO_REUSEPORT 属性(内核 3.9 版本提供的新特性),本文不对 SO_REUSEPORT 做具体介绍,感兴趣的同学自行去学习。

三、客户端的端口可以重复使用吗?

在客户端执行 connect 函数的时候,只要客户端连接的服务器不是同一个,内核允许端口重复使用。

TCP 连接是由四元组(源IP地址,源端口,目的IP地址,目的端口)唯一确认的,那么只要四元组中其中一个元素发生了变化,那么就表示不同的 TCP 连接的。

所以,如果客户端已使用端口 64992 与服务端 A 建立了连接,那么客户端要与服务端 B 建立连接,还是可以使用端口 64992 的,因为内核是通过四元祖信息来定位一个 TCP 连接的,并不会因为客户端的端口号相同,而导致连接冲突的问题。

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

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

相关文章

SpringCloud(五) Eureka与Nacos的区别

SpringCloud(二) Eureka注册中心的使用-CSDN博客 SpringCloud(四) Nacos注册中心-CSDN博客 在这两篇博文中我们详细讲解了Eureka和Nacos分别作为微服务的注册中心的使用方法和注意事项,但是两者之间也有一些区别. 一, Nacos实例分类 Nacos实例分为两种类型: 临时实例:如果实例…

[common c/c++] ring buffer/circular buffer 环形队列/环形缓冲区

前言: ring buffer / circular buffer 又名环形队列 / 环形缓冲区,其通过开辟固定尺寸的内存来实现反复复用同一块内存的目的。由于预先开辟了固定尺寸的内容,所以当数据满的时候,可以有两种处理方式,具体使用哪一种按…

思路视野杂志思路视野杂志社思路视野编辑部2023年第24期目录

公共文化 公共图书馆文旅融合实践与模式思考 白雪1-3 公共图书馆管理与服务创新路径分析 陈静4-6 提升办公室文书档案管理工作的实践探讨 黄强7-9 《思路视野》投稿邮箱:cn7kantougao163.com(注明投稿“《思路视野》”) 崔编辑Q Q :296078736 微信号&am…

ajax-axios发送 get请求 或者 发送post请求带有请求体参数

/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */ !function(e,t){"object"typeof exports&&"object"typeof module?module.exportst():"function"typeof define&&define.amd?define([],t):"object"typeof export…

瑞明达:聚“追梦”之力,共圆“经济梦”

矢志不渝,笃行不怠,争当“一心一意同国行”的无悔“追梦人”。过往几年,国际形势风高浪急,国内环境复杂多变,在后疫情时代、经济恢复压力等多种超预期的因素冲击下,瑞明达团队全面贯彻落实国家发展政策&…

为什么 SIEM 是抵御网络威胁的最佳防御手段

随着 IT 服务和基础设施趋向于混合模式,以及最近数据的激增,组织必须拥有一个集中式安全解决方案来跟踪用户的行为和关键安全事件。 威胁行为者越来越善于检测和利用组织网络中的漏洞,网络攻击也在不断发展。虽然管理员可以对已经发生的攻击…

USART HMI串口屏+单片机通讯上手体验

USART HMI串口屏单片机通讯上手体验 🔖本文采用淘晶驰4.3寸IPS串口屏实物验证,HMI串口屏经简单配置即可快速实现,串口通讯效果。串口屏上手简单,有独立的开发套件,容易上手,驱动显示和功能代码独立。本文仅…

ipv6简单实验案例

R1配置: ipv6 interface GigabitEthernet0/0/0 ipv6 enable ipv6 address auto global ipv6 route-static 2001:21:: 64 2001:12::1 R2配置: ipv6 dhcp enable dhcpv6 pool test address prefix 2001:21::/64 excluded-address 2001:21::1 interface Gi…

EasyExcel复杂表头数据导入

目录 表头示例导入代码数据导出 表头示例 导入代码 Overridepublic void importExcel(InputStream inputStream) {ItemExcelListener itemExcelListener new ItemExcelListener();EasyExcel.read(inputStream, ImportItem.class, itemExcelListener).headRowNumber(2).sheet()…

深入了解汽车级功率MOSFET NVMFS2D3P04M8LT1G P沟道数据表

汽车级功率MOSFET是一种专门用于汽车电子领域的功率MOSFET。它具有高电压、高电流、高温、高可靠性等特点,能够满足汽车电子领域对功率器件的严格要求。汽车级功率MOSFET广泛应用于汽车电机驱动、泵电机控制、车身控制等方面,能够提高汽车电子系统的效率…

Java进阶(List)——面试时List常见问题解读 结合源码分析

前言 List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中List集合的面试问题,结合源码分析题目背后的知识点。 关于的Set的博客文章如下: Java进阶(Set)——面试时…

9.Vue前端使用iframe集成帆软报表的单点登录

一、背景 需要把帆软报表内嵌到若依里面来。 二、帆软设置 2.1 帆软报表的url 打开帆软后端里面的【目录管理】查看具体报表的url 帆软报表的具体地址为: Frm聚合报表地址: 【帆软的服务http】+【/webroot/decision/view/form?viewlet=demo/demo.frm】 CPT普通报表的地…

【腾讯云 HAI域探秘】使用Stable Diffusion大模型生成惊世骇俗的图片!

文章目录 前言环境准备高性能应用服务 HAI资格申请购买HAI高性能服务 生成图片界面汉化:输入提示词生成图片参数列表:根据提示词生成图片 总结:优点:缺点: 前言 AI绘画工具的发展历史可以追溯到2014年,当时…

SQL INNER JOIN 关键字(内部连接)

SQL INNER JOIN 关键字(内部连接) 内部链接INNER JOIN关键字选择两个表中具有匹配值的记录。 SQL INNER JOIN 语法 SELECT column_name(s) FROM table1 INNER JOIN table2 ON table1.column_name table2.column_name; 注释:INNER JOIN 与 …

4.多层感知机-3GPT版

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.1 多层感知机一、感知机1、感知机2、训练感知机3、图形解释4、收敛定理5、XOR问题6、总结 二、多层感知机1、XOR2、单隐藏层3、单隐藏层-单分类4、为什么需要非线性激活函数5、Sigmoid函数6、Tanh函数7、ReLU函数8、多类分…

MFC 窗体插入图片

1.制作BMP图像1.bmp 放到res文件夹下,资源视图界面导入res文件夹下的1.bmp 2.添加控件 控件类型修改为Bitmap 图像,选择IDB_BITMAP1 3.效果

【嵌入式开发学习】__软件工程师的关键原则-18个系统设计概念

目录 前言 01. 域名系统 (DNS) 02. 负载均衡器 03. API 网关 04. 内容交付网络 (CDN) 05. 正向代理与反向代理 06. 缓存 07. 数据分区 08. 数据库复制 09. 分布式消息系统 10. 微服务 11. 数据库 12. 前端缓存 13. 后端缓存 14. 安全性 15. 高可用性与容错性 …

都是80m²小户型,凭啥她家那么好看!福州中宅装饰,福州装修

杨桥新苑 本案来自杨桥新苑的住宅, 质朴弥漫在80㎡的小家, 自然淡雅的木纹,精炼的玄关隔断, 简约的设计里传达着中式的静谧风雅, 简练的空间加入中国元素, 让人从进门开始就沾染一丝艺术气息。 风格&a…

Apache Pulsar 在腾讯云上的最佳实践

导语 由 StreamNative 主办的 Pulsar Meetup Beijing 2023 在2023年10月14日完美落幕,本次活动大咖云集,来自腾讯、滴滴、华为、智联招聘、RisingWave 和 StreamNative 的行业专家们一起,深入探讨 Pulsar 在生产环境中的最佳应用实践&#x…