十七、TCP编程

news2025/4/14 19:09:49

  TCP 编程是网络通信的核心,其 API 围绕面向连接的特性设计,涵盖服务端和客户端的交互流程。以下是基于 ​C 语言的 TCP 编程核心 API 及使用流程的详细解析:


  核心 API 概览

函数角色描述
socket()通用创建套接字,指定协议族(IPv4/IPv6)和类型(SOCK_STREAM)。
bind()服务端将套接字绑定到特定 IP 地址和端口。
listen()服务端将套接字设为监听模式,等待客户端连接请求。
accept()服务端接受客户端连接,返回用于通信的新套接字。
connect()客户端客户端主动连接服务端。
send()/write()通用发送数据(TCP 保证数据顺序,可能拆包/粘包)。
recv()/read()通用接收数据(需处理部分读取和缓冲区管理)。
close()通用关闭套接字,终止连接。
shutdown()通用优雅关闭连接(可选关闭读/写方向)。

1、socket函数

函数原型与头文件
#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

  参数详解

  domain(协议族/地址族)​

  定义通信使用的协议族,常见值包括:

​值​描述
AF_INETIPv4 协议(最常用)
AF_INET6IPv6 协议
AF_UNIX/AF_LOCAL本地进程间通信(UNIX 域套接字)
AF_PACKET底层数据包接口(如原始以太网帧捕获)

  如果是IPV6编程,要使用struct sockddr_in6结构体(man 7 IPV6,通常使用struct sockaddr_storage来编程。

  type(套接字类型)​

指定数据传输的语义,常用类型:

​值​描述
SOCK_STREAM面向连接的流式套接字(TCP,可靠传输)
SOCK_DGRAM无连接的数据报套接字(UDP,尽最大努力交付)
SOCK_RAW原始套接字(直接访问 IP/ICMP 等协议)
protocol(具体协议​)

通常设为 0,表示根据 domaintype ​自动选择默认协议。例如:

  • SOCK_STREAM 默认使用 IPPROTO_TCP
  • SOCK_DGRAM 默认使用 IPPROTO_UDP

若需显式指定协议,可用:

​值​描述
IPPROTO_TCP强制使用 TCP 协议
IPPROTO_UDP强制使用 UDP 协议
IPPROTO_ICMP用于原始套接字的 ICMP 协议

返回值

  • ​成功:返回一个非负整数​(套接字文件描述符),后续操作(如 bind, connect)均基于此描述符。
  • ​失败:返回 -1,并设置 errno 表示错误原因(如 EACCES, EAFNOSUPPORT)。

典型使用场景

创建 TCP 套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
    perror("socket() failed");
    exit(EXIT_FAILURE);
}
  • 用于 HTTP、FTP 等需要可靠传输的应用。
​创建 UDP 套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
    perror("socket() failed");
    exit(EXIT_FAILURE);
}
  • 用于 DNS 查询、实时音视频传输等场景。
创建原始套接字(需 root 权限)​
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd == -1) {
    perror("socket() failed");
    exit(EXIT_FAILURE);
}
  • 可手动构造 IP 或 ICMP 头部,用于网络探测工具(如 ping)。

2、bind函数

  bind() 函数是网络编程中用于将套接字(socket)​与特定的IP地址和端口绑定的关键步骤,常用于服务端设置监听地址。以下是 bind() 的详细解析,包含函数原型、参数解释、使用示例及常见问题:

函数原型
#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数

​参数​类型​描述
sockfdint已创建的套接字描述符(由socket()返回)
addrstruct sockaddr*指向保存绑定地址信息的结构体指针(需根据协议族填充对应的结构类型)
addrlensocklen_t地址结构体的长度(字节数)

地址结构体

​1. IPv4 地址结构 (struct sockaddr_in)
struct sockaddr_in {
    sa_family_t    sin_family;   // 地址族(如 AF_INET)
    in_port_t      sin_port;     // 端口号(需用 `htons()` 转换字节序)
    struct in_addr sin_addr;     // IPv4 地址(需用 `inet_pton()` 或 `htonl(INADDR_ANY)`)
    unsigned char  sin_zero[8];  // 填充字段(一般置零)
};

struct in_addr {
    uint32_t s_addr;            // 32位 IPv4 地址(网络字节序)
};
​2. IPv6 地址结构 (struct sockaddr_in6)
struct sockaddr_in6 {
    sa_family_t     sin6_family;   // 地址族(AF_INET6)
    in_port_t       sin6_port;     // 端口号(网络字节序)
    uint32_t        sin6_flowinfo; // IPv6 流信息(通常为0)
    struct in6_addr sin6_addr;     // IPv6 地址
    uint32_t        sin6_scope_id; // 接口范围标识符(用于本地链路地址)
};

struct in6_addr {
    unsigned char s6_addr[16];     // 128位 IPv6 地址
};
​3. 通用地址结构 (struct sockaddr)
struct sockaddr {
    sa_family_t sa_family;  // 地址族(AF_xxx)
    char        sa_data[14];// 具体地址数据(由子结构展开填充)
};

  使用场景与示例

​1. 服务端绑定 IP 和端口
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) { perror("socket"); exit(1); }

// 允许地址重用(避免服务端重启时 bind 失败)
int optval = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;                       // IPv4
addr.sin_addr.s_addr = htonl(INADDR_ANY);        // 绑定所有本地 IP
addr.sin_port = htons(8080);                     // 绑定端口 8080

if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
    perror("bind");
    close(server_fd);
    exit(1);
}

// 后续可调用 listen() 启动监听
​2. 客户端绑定特定源地址
int client_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in client_addr = {0};
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(12345);             // 指定客户端端口
inet_pton(AF_INET, "192.168.1.100", &client_addr.sin_addr); // 指定源 IP

bind(client_fd, (struct sockaddr*)&client_addr, sizeof(client_addr));
connect(client_fd, server_addr, sizeof(server_addr));

3、listen函数

函数原型
#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd, int backlog);

  参数详解

参数类型描述
sockfdint已通过 bind() 绑定地址的套接字描述符(必须是 ​SOCK_STREAM 类型)。
backlogint已建立连接(完成三次握手)的队列最大长度,决定同时等待 accept() 处理的连接数。

  核心作用

  1. ​转换套接字状态:

    • 将套接字从主动模式​(默认)转为被动模式,使其能够接收客户端的连接请求。
    • 未调用 listen() 的套接字无法调用 accept()
  2. ​管理连接队列:

    • 内核为监听套接字维护两个队列​(具体实现可能因操作系统而异):
      • ​未完成队列(SYN_RCVD 状态)​:客户端已发送 SYN,但未完成三次握手。
      • ​已完成队列(ESTABLISHED 状态)​:已完成三次握手,等待 accept() 取出。
    • backlog 参数通常指已完成队列的最大长度​(Linux 中默认上限由 /proc/sys/net/core/somaxconn 定义)。

  使用场景与示例

​1. 服务端启动监听
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
// ...绑定地址(bind())...

// 设置监听队列长度为 128
if (listen(server_fd, 128) == -1) {
    perror("listen() failed");
    close(server_fd);
    exit(EXIT_FAILURE);
}

// 循环接受客户端连接
while (1) {
    struct sockaddr_in client_addr;
    socklen_t addrlen = sizeof(client_addr);
    int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addrlen);
    // ...处理 client_fd...
}
​2. backlog 的合理取值
​经验值:通常设为 SOMAXCONN(系统定义的最大值,如 Linux 默认 4096)。
​调整方法​(Linux):

# 临时修改 somaxconn
echo 4096 > /proc/sys/net/core/somaxconn

# 永久修改(需编辑 /etc/sysctl.conf)
net.core.somaxconn = 4096
  • 注意:实际允许的连接数受系统资源和并发模型(如多线程、epoll)影响。

4、accept函数

函数原型
#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

  参数详解

​参数

​类型

​描述

sockfd

int

处于监听状态的套接字描述符(由 listen() 设置)。

addr

struct sockaddr*

输出参数,用于存储客户端地址信息(如 IP 和端口)。若不需要可设为 NULL

addrlen

socklen_t*

输入输出参数:传入 addr 缓冲区的长度,返回实际写入的地址长度。若 addrNULL,可设为 NULL


  返回值

  • ​成功:返回一个新的已连接套接字描述符​(非负整数),专门用于与客户端通信。

  • ​失败:返回 -1,并设置 errno(如 EINTRECONNABORTED)。


  核心作用

  1. ​提取连接:从监听套接字的已完成连接队列​(已完成三次握手)中取出一个客户端连接。

  2. ​生成新套接字:返回的已连接套接字与客户端一一对应,原监听套接字继续接受其他连接。

  3. ​获取客户端地址:通过 addr 参数获取客户端的 IP 地址和端口(可选)。

5、connect函数

函数原型
#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

  参数详解

参数类型描述
sockfdint客户端套接字描述符(由 socket() 创建)。
addrstruct sockaddr*指向服务端地址结构体的指针(如 sockaddr_in)。
addrlensocklen_t地址结构体的长度(单位:字节)。

  返回值

  • 成功:返回 0,套接字进入已连接状态(TCP)或设置默认地址(UDP)。
  • 失败:返回 -1,并设置 errno 表示错误原因。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小甲鱼第004讲:变量和字符串(下)| 课后测试题及答案

问答题: 0. 请问下面代码有没有毛病&#xff0c;为什么? 请问下面代码为什么会出错&#xff0c;应该如何解决&#xff1f; 答:这是由于在字符串中&#xff0c;反斜杠()会与其随后的字符共同构成转义字符。 为了避免这种不测情况的发生&#xff0c;我们可以在字符串的引号前面…

MergeX亮相GTC2025:开启全球广告流量交易新篇章

全球流量盛宴GTC2025深圳启幕&#xff0c;共探出海新蓝海 2025年4月24日至25日&#xff0c;GTC2025全球流量大会将在深圳福田会展中心9号馆隆重召开。作为跨境出海领域内规模最大、资源最丰富、产业链最完备的年度盛会&#xff0c;此次大会将汇聚众多行业精英&#xff0c;共同探…

STM32(基于标准库)

参考博客&#xff1a;江科大STM32笔记 Stm32外设 一、GPIO 基础 GPIO位结构 I/O引脚的保护二极管是对输入电压进行限幅的上面的二极管接VDD, 3.3V,下面接VSS, 0V&#xff0c;当输入电压 >3.3V 那上方这个二极管就会导通&#xff0c;输入电压产生的电流就会大部分充入VD…

国家优青ppt美化_青年科学基金项目B类ppt案例模板

国家优青 国家优青&#xff0c;全称“国家优秀青年基金获得者”。2025改名青年科学基金B类。 作为自然基金人才资助类型&#xff0c;支持青年学者在基础研究方面自主选择研究方向开展创新研究。它是通往更高层次科研荣誉的重要阶梯&#xff0c;是准杰青梯队。 / WordinPPT /…

解决 ECharts 图表无数据显示问题

问题&#xff1a; 在开发项目时&#xff0c;后端明明已经成功返回了数据&#xff0c;但在展示手账发布数量趋势和树洞帖子发布数量趋势的 ECharts 图表中&#xff0c;却只有坐标轴&#xff0c;没有任何数据显示。 以我的VUE项目开发可视化面板为例&#xff0c;下面将详细分析可…

spacy安装失败报错

报错 使用命令pip install spacy安装spacy时总是报错&#xff08;python -m pip install spacy方式安装同样报错&#xff09; 解决办法 使用conda安装&#xff0c;conda能够避免很多不必要的依赖包。 命令&#xff1a;conda install spacy 安装成功列表展示

C++在Linux上生成动态库并调用接口测试

加减乘除demo代码 项目结构 CPP/ ├── calculator.cpp ├── calculator.h ├── main.cpp 头文件 #ifndef CALCULATOR_H #define CALCULATOR_H#ifdef __cplusplus extern "C" {#endifdouble add(double a, double b);double subtract(double a, double b…

前端性能测试工具 —— WebPageTest

测试工具介绍 WebPageTest 是一个用于测量和分析网页性能的工具。它提供了详细的诊断信息&#xff0c;帮助用户了解网页在不同条件下的表现。用户可以选择全球不同的测试地点&#xff0c;使用真实的浏览器&#xff0c;并自定义网络条件进行测试。WebPageTest 还支持核心网络指…

北邮LLMs在导航中的应用与挑战!大模型在具身导航中的应用进展综述

作者&#xff1a;Jinzhou Lin, Han Gao, Xuxiang Feng, Rongtao Xu, Changwei Wang, Man Zhang, Li Guo, Shibiao Xu 单位&#xff1a;北京邮电大学人工智能学院&#xff0c;中国科学院自动化研究所多模态人工智能系统国家重点实验室&#xff0c;中科院空间信息研究所&#xf…

Windows下ElasticSearch8.x的安装步骤

下载ElasticSearch&#xff1a;https://www.elastic.co/downloads/elasticsearch &#xff08;我下载的是目前最新版8.17.4&#xff09;解压ElasticSearch 进入到ElasticSearch的bin目录下双击elasticsearch.bat 弹出控制台并开始执行&#xff0c;在这一步会输出初始账号和密码…

【高性能缓存Redis_中间件】一、快速上手redis缓存中间件

一、铺垫 在当今的软件开发领域&#xff0c;消息队列扮演着至关重要的角色。它能够帮助我们实现系统的异步处理、流量削峰以及系统解耦等功能&#xff0c;从而提升系统的性能和可维护性。Redis 作为一款高性能的键值对数据库&#xff0c;不仅提供了丰富的数据结构&#xff0c;…

AI Agent入门指南

图片来源网络 ‌一、开箱暴击&#xff1a;你以为的"智障音箱"&#xff0c;其实是赛博世界的007‌ ‌1.1 从人工智障到智能叛逃&#xff1a;Agent进化史堪比《甄嬛传》‌ ‌青铜时代&#xff08;2006-2015&#xff09;‌ “小娜同学&#xff0c;关灯” “抱歉&…

海洋大地测量基准与水下导航系列之八我国海洋水下定位装备发展现状

中国国家综合PNT体系建设重点可概括为“51N”&#xff0c;“5”指5大基础设施&#xff0c;包括重点推进下一代北斗卫星导航系统、积极发展低轨导航增强系统、按需发展水下导航系统、大力发展惯性导航系统、积极探索脉冲星导航系统&#xff1b;“1”是实现1个融合发展&#xff0…

谷歌开源代理开发工具包(Agent Development Kit,ADK):让多智能体应用的构建变得更简

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

noscript 标签是干什么的

vue public目录下的 index.html 会有 <noscript> 标签不知道是干吗的。 其实 noscript 标签在不支持或是禁用JavaScript 的浏览器中显示替代的内容。这个元素可以包含任何 HTML 元素。这个标签的用法也非常简单&#xff1a; <noscript><strong>Were sorry …

[创业之路-366]:投资尽职调查 - 尽调核心逻辑与核心影响因素:价值、估值、退出、风险、策略

目录 一、VC投资的本质是冒着不确定性风险进行买卖、生意&#xff0c;为了赚取高额回报 1、VC投资的核心本质 2、VC投资的运作机制 3、VC投资的风险与挑战 4、VC投资的底层逻辑 5、总结&#xff1a;VC投资的本质再定义 二、尽调核心逻辑 1、尽调的含义 2、尽调的逻辑方…

Hyprnote开源程序是一款记录和转录您会议的 AI 记事本。 本地优先且可扩展 。

一、软件介绍 文末提供源码下载学习 Hyprnote开源程序是一款记录和转录您会议的 AI 记事本。 从您的原始会议记录中生成强大的摘要&#xff0c;本地优先且可扩展 。使用开源模型 &#xff08;Whisper & Llama&#xff09; 离线工作&#xff0c;高度可扩展 &#xff0c;由插…

上篇:新能源轻卡城配物流经济/动力模式量化定义(理论篇)——数学暴力破解工程困局

副标题&#xff1a;用微分方程撕开模式切换本质&#xff0c;用传感器数据重构载重真相 引言&#xff1a;为什么轻卡模式定义比乘用车难10倍&#xff1f; 行业现状痛点&#xff1a; 中国新能源轻卡日均载重波动高达300%&#xff08;空载0kg→满载4.5吨&#xff09;某头部车企实…

Ubuntu22环境下,Docker部署阿里FunASR的gpu版本

番外: 随着deepseek的爆火,人工智能相关的开发变得异常火爆,相关的大模型开发很常见的agent智能体需要ASR语音识别的功能,阿里开源的FunASR几乎是把一个商业的项目放给我们使用了。那么我们项目中的生产环境怎么部署gpu版本的语音识别服务呢?经过跟deepseek的一上午的极限…

内网邮箱服务器搭建-详解

目录 一、背景 二、搭建邮箱需要具备的基础知识 1、smtp&#xff08;Simple Mail Transfer Protocol&#xff09; SMTP工作原理 SMTP 命令 SMTP 协议端口 2、pop3&#xff08;Post Office Protocol&#xff09; POP3特点 POP3工作原理 3、imap4&#xff08;Internet M…