网络基础学习

认识端口号

-端口号是一个2字节16位的整数;

  • 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理;
  • IP地址 + 端口号能够标识网络上的某一台主机的某一个进程;
  • 一个端口号只能被一个进程占用.

认识TCP协议

TCP(Transmission Control Protocol 传输控制协议)

  • 传输层协议
  • 有连接
  • 可靠传输(代表效率相对较低)
  • 面向字节流

在这里插入图片描述

  • 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去
  • 32位序号/32位确认号
  • 4位TCP报头长度: 表示该TCP头部有多少个32位bit(有多少个4字节); 所以TCP头部最大长度是15 * 4 = 60
  • 6位标志位
    URG: 紧急指针是否有效
    ACK: 确认号是否有效
    PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
    RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
    SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
    FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
  • 16位窗口大小:填充的是自身的接受缓冲区中剩余空间的大小,支持流量控制
  • 16位校验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP首部, 也包含TCP数据部分.
  • 16位紧急指针: 标识哪部分数据是紧急数据
  • 40字节头部选项

TCP如何决定有效载荷和报头如何分离?

先读取前20个字节,提取出其中4位首部长度,然后让首部长度✖4,就是报头大小,就可以将报头和有效载荷分离出来。

TCP如何决定将自己的有效载荷交付给上层的那个协议?

目的端口号就可以决定将有效载荷交给谁

TCP建立连接

tcp建立连接就是三次握手
在这里插入图片描述
这就是三次握手。
三次握手属于通信细节!!上层用户不需要关心,双方OS(TCP)自动完成。

TCP断开连接

在这里插入图片描述

TCP的可靠性

什么是可靠性?什么是真正的可靠性?

一般而言,我们认为只有我发的消息收到了回应,才算我发的消息可靠的被对方收到。

一般而言,发送的数据都要有响应,这是保证可靠性的底层策略,这就是确认应答机制。

确认应答机制

在这里插入图片描述
TCP将每个字节的数据都进行了编号. 即为序列号(保证可靠性)
在这里插入图片描述
每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发。

为什么TCP要用两套序号机制——确认序号和序号?

因为TCP是全双工的。可能同时双方都在进行通信。

超时重传机制

在这里插入图片描述
如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发
但是, 主机A未收到B发来的确认应答, 也可能是因为ACK丢失了
在这里插入图片描述
因此主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉. 这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果.

认识UDP协议

UDP(User Datagram Protocol 用户数据报协议)

  • 传输层协议
  • 无连接
  • 不可靠传输
  • 面向数据报

UDP协议端格式

在这里插入图片描述

  • 16位源端口和16位目的端口代表从哪里来到哪里去
  • 16位UDP长度代表整个数据报(UDP首部+UDP数据)的最大长度

UDP的特点

UDP传输的过程类似于寄信

  • 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接
  • 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
  • 面向数据报: 不能够灵活的控制读写数据的次数和数量

UDP如何保证自己的报头和有效载荷分离?

*****UDP是定长报头(8字节)

UDP如何让决定自己的有效载荷交付给上层的那个协议?

*****因为有目的端口号

什么叫做报头?

UDP是属于内核协议栈(C语言),用C语言是如何标识报头呢?

传输层是如何通过端口号找到对应的服务器的进程

socket编程接口

socket 常见API

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);

// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,
socklen_t address_len);

// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);

// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,
socklen_t* address_len);

// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);

sockaddr结构

套接字不仅支持跨网络的进程间通信,还支持本地的进程间通信(域间套接字)。在进行跨网络通信时我们需要传递的端口号和IP地址,而本地通信则不需要,因此套接字提供了sockaddr_in结构体和sockaddr_un结构体,其中sockaddr_in结构体是用于跨网络通信的,而sockaddr_un结构体是用于本地通信的。
为了让套接字的网络通信和本地通信能够使用同一套函数接口,于是就出现了sockeaddr结构体,该结构体与sockaddr_in和sockaddr_un的结构都不相同,但这三个结构体头部的16个比特位都是一样的,这个字段叫做协议家族。
在这里插入图片描述

传输层

再谈端口号

端口号(Port)标识了一个主机上进行通信的不同的应用程序;
在这里插入图片描述
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过netstat -n查看);
在这里插入图片描述
在这里插入图片描述

一个进程是否可以bind多个端口号

可以的

一个端口号是否可以被多个进程bind

这是不行的,因为一个端口号只能标识唯一一个进程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值