Linux——网络(tcp)

文章目录


目录

文章目录

前言

一、TCP逻辑

1. 面向连接

三次握手(建立连接)

四次挥手(关闭连接)

2. 可靠性

3. 流量控制

4. 拥塞控制

5. 基于字节流

6. 全双工通信

7. 状态机

8. TCP头部结构

9. TCP的应用场景

二、编写tcp代码函数

1. Socket 创建与配置

socket()

setsockopt()

2. 绑定与监听

bind()

listen()

3. 连接与接受连接

connect()

accept()

4. 数据发送与接收

send()

recv()

5. 关闭连接

close()

shutdown()

6. 地址转换与解析

inet_pton()

inet_ntop()

7. 错误处理

perror()

strerror()

三、基本客服端和服务端

1、服务端

2、客户端

总结


前言

Linux——网络基础(1)-CSDN博客

Linux——网络(udp)-CSDN博客

  1. TCP协议概述:简要介绍TCP协议的基本特性,包括连接建立、数据传输、流量控制、拥塞控制等。

  2. Linux网络编程基础:介绍Linux下的Socket编程接口,以及如何使用这些接口进行TCP通信。

  3. TCP服务器与客户端的实现:通过实际的代码示例,展示如何编写一个简单的TCP服务器和客户端程序。

  4. TCP协议的性能优化:探讨如何通过调整TCP参数、使用非阻塞I/O、多线程/多进程等技术来提升TCP应用的性能。

  5. 常见问题与调试技巧:分享一些在实际开发中可能遇到的TCP相关问题,以及如何使用工具进行网络调试和故障排查。


一、TCP逻辑

1. 面向连接

TCP是一种面向连接的协议,这意味着在数据传输之前,通信双方需要先建立一个连接。连接的建立和关闭是通过三次握手和四次挥手来完成的。

三次握手(建立连接)
  1. SYN:客户端向服务器发送一个SYN(同步)报文,表示请求建立连接。

  2. SYN-ACK:服务器收到SYN后,回复一个SYN-ACK(同步-确认)报文,表示同意建立连接。

  3. ACK:客户端收到SYN-ACK后,发送一个ACK(确认)报文,连接正式建立。

四次挥手(关闭连接)
  1. FIN:主动关闭方(客户端或服务器)发送一个FIN(结束)报文,表示希望关闭连接。

  2. ACK:被动关闭方收到FIN后,回复一个ACK报文,表示确认收到关闭请求。

  3. FIN:被动关闭方完成数据发送后,发送一个FIN报文,表示自己也准备关闭连接。

  4. ACK:主动关闭方收到FIN后,回复一个ACK报文,连接正式关闭。


2. 可靠性

TCP通过以下机制确保数据的可靠传输:

  • 序列号与确认机制:每个TCP报文都包含一个序列号(Sequence Number),接收方通过发送确认号(Acknowledgment Number)来确认已收到的数据。如果发送方未收到确认,则会重传数据。

  • 超时重传:如果发送方在一定时间内未收到确认,则会重新发送数据。

  • 数据校验:TCP使用校验和(Checksum)来检测数据在传输过程中是否损坏。


3. 流量控制

TCP通过滑动窗口机制实现流量控制,防止发送方发送数据过快导致接收方缓冲区溢出。

  • 接收窗口:接收方通过TCP头部中的窗口字段告知发送方自己当前可接收的数据量。

  • 动态调整:接收方可以根据自身缓冲区的可用空间动态调整窗口大小。


4. 拥塞控制

TCP通过拥塞控制算法避免网络拥塞,常见的算法包括:

  • 慢启动(Slow Start):初始时发送方以较小的窗口发送数据,随后指数增长。

  • 拥塞避免(Congestion Avoidance):当窗口达到阈值后,发送方以线性方式增加窗口大小。

  • 快速重传(Fast Retransmit):当发送方收到三个重复的ACK时,立即重传丢失的报文。

  • 快速恢复(Fast Recovery):在快速重传后,发送方进入快速恢复阶段,避免窗口大幅减小。


5. 基于字节流

TCP是一种基于字节流的协议,这意味着:

  • 无消息边界:TCP将数据视为连续的字节流,不保留发送方写入的数据边界。例如,发送方发送两次数据(“Hello”和“World”),接收方可能一次性收到“HelloWorld”。

  • 粘包与拆包:由于TCP的字节流特性,接收方需要自己处理数据的边界问题(如通过长度字段或特殊分隔符)。


6. 全双工通信

TCP支持全双工通信,即通信双方可以同时发送和接收数据。每个TCP连接由两个独立的流组成:

  • 一个流用于从客户端到服务器的数据传输。

  • 另一个流用于从服务器到客户端的数据传输。


7. 状态机

TCP连接的生命周期由一个状态机管理,常见的状态包括:

  • LISTEN:服务器等待客户端连接。

  • SYN_SENT:客户端已发送SYN,等待服务器响应。

  • SYN_RECEIVED:服务器已收到SYN并发送SYN-ACK,等待客户端确认。

  • ESTABLISHED:连接已建立,可以传输数据。

  • FIN_WAIT_1 / FIN_WAIT_2:主动关闭方等待对方的FIN或ACK。

  • CLOSE_WAIT:被动关闭方等待应用程序关闭连接。

  • TIME_WAIT:连接关闭后,等待可能出现的延迟报文。


8. TCP头部结构

TCP头部包含以下关键字段:

  • 源端口和目的端口:标识通信的应用程序。

  • 序列号和确认号:用于数据排序和确认。

  • 标志位:如SYN、ACK、FIN等,用于控制连接状态。

  • 窗口大小:用于流量控制。

  • 校验和:用于数据完整性校验。


9. TCP的应用场景

TCP适用于需要可靠传输的场景,例如:

  • Web浏览(HTTP/HTTPS)

  • 文件传输(FTP)

  • 电子邮件(SMTP/POP3/IMAP)

  • 远程登录(SSH/Telnet)


二、编写tcp代码函数

1. Socket 创建与配置

socket()
  • 功能:创建一个新的套接字(socket),用于网络通信。

  • 原型:

    int socket(int domain, int type, int protocol);
  • 参数:

    • domain:协议族,如 AF_INET(IPv4)或 AF_INET6(IPv6)。

    • type:套接字类型,如 SOCK_STREAM(TCP)或 SOCK_DGRAM(UDP)。

    • protocol:通常为 0,表示默认协议。

  • 返回值:成功返回套接字文件描述符,失败返回 -1

setsockopt()
  • 功能:设置套接字选项,如重用地址、调整缓冲区大小等。

  • 原型:

    int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
  • 常用选项:

    • SO_REUSEADDR:允许重用本地地址。

    • SO_RCVBUF / SO_SNDBUF:调整接收/发送缓冲区大小。


2. 绑定与监听

bind()
  • 功能:将套接字绑定到本地地址和端口。

  • 原型:

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 参数:

    • sockfd:套接字文件描述符。

    • addr:指向 struct sockaddr 的指针,包含地址和端口信息。

    • addrlen:地址结构体的长度。

listen()
  • 功能:将套接字设置为监听模式,等待客户端连接。

  • 原型:

    int listen(int sockfd, int backlog);
  • 参数:

    • sockfd:套接字文件描述符。

    • backlog:等待连接队列的最大长度。


3. 连接与接受连接

connect()
  • 功能:客户端使用该函数连接到服务器。

  • 原型:

    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 参数:

    • sockfd:套接字文件描述符。

    • addr:指向服务器地址结构体的指针。

    • addrlen:地址结构体的长度。

accept()
  • 功能:服务器接受客户端的连接请求,返回一个新的套接字用于通信。

  • 原型:

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 参数:

    • sockfd:监听套接字文件描述符。

    • addr:用于存储客户端地址信息。

    • addrlen:地址结构体的长度。


4. 数据发送与接收

send()
  • 功能:通过已连接的套接字发送数据。

  • 原型:

    ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 参数:

    • sockfd:套接字文件描述符。

    • buf:指向要发送数据的缓冲区。

    • len:数据长度。

    • flags:标志位,通常为 0

recv()
  • 功能:通过已连接的套接字接收数据。

  • 原型:

    ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • 参数:

    • sockfd:套接字文件描述符。

    • buf:指向接收数据的缓冲区。

    • len:缓冲区长度。

    • flags:标志位,通常为 0


5. 关闭连接

close()
  • 功能:关闭套接字,释放资源。

  • 原型:

    int close(int sockfd);
  • 参数:

    • sockfd:套接字文件描述符。

shutdown()
  • 功能:优雅地关闭连接,可以选择关闭读、写或读写通道。

  • 原型:

    int shutdown(int sockfd, int how);
  • 参数:

    • sockfd:套接字文件描述符。

    • how:关闭方式,如 SHUT_RD(关闭读)、SHUT_WR(关闭写)、SHUT_RDWR(关闭读写)。


6. 地址转换与解析

inet_pton()
  • 功能:将点分十进制的IP地址转换为二进制格式。

  • 原型:

    int inet_pton(int af, const char *src, void *dst);
  • 参数:

    • af:地址族,如 AF_INET 或 AF_INET6

    • src:点分十进制字符串。

    • dst:存储二进制结果的缓冲区。

inet_ntop()
  • 功能:将二进制格式的IP地址转换为点分十进制字符串。

  • 原型:

    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
    getaddrinfo()
  • 功能:解析主机名和服务名,返回地址信息。

  • 原型:

    int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);

7. 错误处理

perror()
  • 功能:打印与 errno 相关的错误信息。

  • 原型:

    void perror(const char *s);
strerror()
  • 功能:将错误码转换为可读的字符串。

  • 原型:

    char *strerror(int errnum);

三、基本客服端和服务端

1、服务端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {int server_fd, new_socket;struct sockaddr_in address;int addrlen = sizeof(address);char buffer[BUFFER_SIZE] = {0};char *response = "Hello from server";// 1. 创建套接字if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("Socket failed");exit(EXIT_FAILURE);}// 2. 绑定地址和端口address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY; // 监听所有网络接口address.sin_port = htons(PORT);if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("Bind failed");close(server_fd);exit(EXIT_FAILURE);}// 3. 监听连接if (listen(server_fd, 3) < 0) {perror("Listen failed");close(server_fd);exit(EXIT_FAILURE);}printf("Server listening on port %d...\n", PORT);// 4. 接受客户端连接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("Accept failed");close(server_fd);exit(EXIT_FAILURE);}// 5. 读取客户端数据int valread = read(new_socket, buffer, BUFFER_SIZE);printf("Client says: %s\n", buffer);// 6. 发送响应给客户端send(new_socket, response, strlen(response), 0);printf("Response sent to client\n");// 7. 关闭连接close(new_socket);close(server_fd);return 0;
}

2、客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {int sock = 0;struct sockaddr_in serv_addr;char buffer[BUFFER_SIZE] = {0};char *message = "Hello from client";// 1. 创建套接字if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("Socket creation failed");exit(EXIT_FAILURE);}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);// 2. 将IP地址从字符串转换为二进制格式if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {perror("Invalid address/ Address not supported");close(sock);exit(EXIT_FAILURE);}// 3. 连接到服务器if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("Connection failed");close(sock);exit(EXIT_FAILURE);}// 4. 发送数据到服务器send(sock, message, strlen(message), 0);printf("Message sent to server\n");// 5. 接收服务器的响应int valread = read(sock, buffer, BUFFER_SIZE);printf("Server says: %s\n", buffer);// 6. 关闭连接close(sock);return 0;
}


总结

TCP网络编程是构建高性能、高可靠性网络应用的基础。通过理解TCP协议的工作原理、掌握Linux Socket API的使用方法,并实践编写客户端和服务器程序,我们可以逐步掌握网络编程的核心技能。希望本篇博客能为你的学习之旅提供帮助,期待你在网络编程的世界中探索更多可能性!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter使用Flavor实现切换环境和多渠道打包

在Android开发中通常我们使用flavor进行多渠道打包&#xff0c;flutter开发中同样有这种方式&#xff0c;不过需要在原生中配置 具体方案其实flutter官网个了相关示例&#xff08;https://docs.flutter.dev/deployment/flavors&#xff09;,我这里记录一下自己的操作 Android …

MySQL备忘录

MySQL 的一些基础知识记录&#xff0c;包括一些配置文件&#xff0c;cmd命令等 前言 这里使用的MySQL版本是8.0.25 MySQL安装&#xff0c;包括相关配置文件文本内容&#xff0c;相关cmd命令 通过安装包配置环境变量使用cmd管理员权限通过命令安装MySQL 8.0.25 一、安装配置 …

Prompt提示词完整案例:让chatGPT成为“书单推荐”的高手

大家好&#xff0c;我是老六哥&#xff0c;我正在共享使用AI提高工作效率的技巧。欢迎关注我&#xff0c;共同提高使用AI的技能&#xff0c;让AI成功你的个人助理。 许多人可能会跟老六哥一样&#xff0c;有过这样的体验&#xff1a;当我们遇到一个能力出众或对事物有独到见解的…

Maui学习笔记- SQLite简单使用案例02添加详情页

我们继续上一个案例&#xff0c;实现一个可以修改当前用户信息功能。 当用户点击某个信息时&#xff0c;跳转到信息详情页&#xff0c;然后可以点击编辑按钮导航到编辑页面。 创建项目 我们首先在ViewModels目录下创建UserDetailViewModel。 实现从详情信息页面导航到编辑页面…

Linux文件原生操作

Linux 中一切皆文件&#xff0c;那么 Linux 文件是什么&#xff1f; 在 Linux 中的文件 可以是&#xff1a;传统意义上的有序数据集合&#xff0c;即&#xff1a;文件系统中的物理文件 也可以是&#xff1a;设备&#xff0c;管道&#xff0c;内存。。。(Linux 管理的一切对象…

HttpClient学习

目录 一、概述 二、HttpClient依赖介绍 1.导入HttpClient4依赖 2.或者导入HttpClient5依赖 3.二者区别 三、HttpClient发送Get请求和Post请求测试 (一)通过HttpClient发送Get请求 (二)通过HttpClient发送Post请求 一、概述 HttpClient是 Apache 软件基金会提供的一…

【重生之我在学习C语言指针详解】

目录 ​编辑 --------------------------------------begin---------------------------------------- 引言 一、指针基础 1.1 内存地址 1.2 指针变量 1.3 指针声明 1.4 取地址运算符 & 1.5 解引用运算符 *** 二、指针运算 2.1 指针加减运算 2.2 指针关系运算 三…

< OS 有关> BaiduPCS-Go 程序的 菜单脚本 Script: BaiduPCS-Go.Menu.sh (bdgo.sh)

目标&#xff1a; 使用 日本阿里云的 VPM 传输文件。 暂时方案&#xff1a; 使用 主机JPN 下载 https://huggingface.co/ 上模型从 JPN 放到 度狗上在家里从狗度下载 为了减少编程&#xff0c;尽量使用现在软件 &#xff0c;就找到 GitHub - qjfoidnh/BaiduPCS-Go: iikira…

98.1 AI量化开发:长文本AI金融智能体(Qwen-Long)对金融研报大批量处理与智能分析的实战应用

目录 0. 承前1. 简介1.1 通义千问(Qwen-Long)的长文本处理能力 2. 基础功能实现2.1 文件上传2.2 单文件分析2.3 多文件分析 3. 汇总代码&运行3.1 封装的工具函数3.2 主要功能特点3.3 使用示例3.4 首次运行3.5 运行结果展示 4. 注意事项4.1 文件要求4.2 错误处理机制4.3 最佳…

Linux环境基础开发工具的使用(apt, vim, gcc, g++, gbd, make/Makefile)

目录 什么是软件包 Linux 软件包管理器 apt 认识apt 查找软件包 安装软件 如何实现本地机器和云服务器之间的文件互传 卸载软件 Linux编辑器 - vim vim的基本概念 vim下各模式的切换 vim命令模式下各指令汇总 vim底行模式个指令汇总 Linux编译器 - gcc/g gcc/g的作…

deepseek R1的确不错,特别是深度思考模式

deepseek R1的确不错&#xff0c;特别是深度思考模式&#xff0c;每次都能自我反省改进。比如我让 它写文案&#xff1a; 【赛博朋克版程序员新春密码——2025我们来破局】 亲爱的代码骑士们&#xff1a; 当CtrlS的肌肉记忆遇上抢票插件&#xff0c;当Spring Boot的…

SpringBoot源码解析(八):Bean工厂接口体系

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args Sp…

基于Django的个人博客系统的设计与实现

【Django】基于Django的个人博客系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 系统采用Python作为主要开发语言&#xff0c;结合Django框架构建后端逻辑&#xff0c;并运用J…

Vue-day2

7.Vue的生命周期 mounted函数&#xff1a;在页面加载完毕时&#xff0c;发送异步请求&#xff0c;加载数据&#xff0c;渲染页面 createApp({date(){},methods:{},mounted:function(){console.log(Vue挂载完毕&#xff0c;发送请求获取数据)} }).mount(#{app}) 8.ajax函数库…

SSM-MyBatis-总结

文章目录 一、Hello MyBatis1.1 流程1.2 总结 二、Crud 的一些注意点三、参数传递3.1 #{ } VS ${ }3.2 单、复参数传递&#xff08;1&#xff09;单参数&#xff08;2&#xff09;多参数 -- Param&#xff08;3&#xff09;总结 四、查询结果返回--结果封装4.1 ResultType 一般…

全面解析文件上传下载删除漏洞:风险与应对

在数字化转型的时代&#xff0c;文件上传、下载与删除功能已经成为各类应用程序的标准配置&#xff0c;从日常办公使用的协同平台&#xff0c;到云端存储服务&#xff0c;再到社交网络应用&#xff0c;这些功能在给用户带来便捷体验、显著提升工作效率的同时&#xff0c;也隐藏…

GSI快速收录服务:让你的网站内容“上架”谷歌

辛苦制作的内容无法被谷歌抓取和展示&#xff0c;导致访客无法找到你的网站&#xff0c;这是会让人丧失信心的事情。GSI快速收录服务就是为了解决这种问题而存在的。无论是新上线的页面&#xff0c;还是长期未被收录的内容&#xff0c;通过我们的技术支持&#xff0c;都能迅速被…

JavaScript

书写位置 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/*C…

Go的内存逃逸

Go的内存逃逸 内存逃逸是 Go 语言中一个重要的概念&#xff0c;指的是本应分配在栈上的变量被分配到了堆上。栈上的变量在函数结束后会自动回收&#xff0c;而堆上的变量需要通过垃圾回收&#xff08;GC&#xff09;来管理&#xff0c;因此内存逃逸会增加 GC 的压力&#xff0…

python学opencv|读取图像(四十九)原理探究:使用cv2.bitwise()系列函数实现图像按位运算

【0】基础定义 按位与运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;全1取1&#xff0c;其余取0。 按位或运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;有1取1&#xff0c;其余取0。 按位异或运算&#xff1a; 两个等长度二进制数上下对齐&#xff0c;相…