102.套接字-Socket网络编程4(TCP通信流程)
目录
TCP编程流程
套接字函数
1.创建套接字
2.绑定地址
3.监听连接请求
4.接受连接
5. 连接到服务器
6. 发送数据
7. 接收数据
8.关闭套接字
服务器端通信流程
示例代码
客户端通信流程
代码示例
TCP编程流程
TCP是一个面向连接的,安全的,流式传输协议,这个协议是一个传输层协议。
- 面向连接:是一个双向连接,通过三次握手完成,断开连接需要通过四次挥手完成。
- 安全:tcp通信过程中,会对发送的每一数据包都会进行校验, 如果发现数据丢失, 会自动重传
- 流式传输:发送端和接收端处理数据的速度,数据的量都可以不一致。
TCP 的服务器端和客户端编程流程如下:

套接字函数
套接字编程中,常用的套接字函数通常涵盖套接字的创建、绑定、监听、连接、发送、接收、关闭等操作。以下是一些常用的套接字函数,这些函数通常在C语言的
<sys/socket.h>头文件中声明:1.创建套接字
int socket(int domain, int type, int protocol);
参数:
domain:使用的地址协议族,如AF_INET、AF_INET6分别表示IPv4、IPv6格式。type:套接字类型,如 SOCK_STREAM(流式传输协议)表示TCP套接字,SOCK_DGRAM(报式传输协议)表示UDP套接字。protocol:通常为0,表示自动选择协议。返回值:
- 成功:返回新创建套接字的文件描述符。
- 失败:返回-1,并设置
errno。2.绑定地址
// 将文件描述符和本地的IP与端口进行绑定 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
sockfd:套接字的文件描述符,通过socket调用得到的返回值。addr:包含要绑定的IP地址和端口号的结构体。addrlen:addr结构体的大小,sizeof(addr)。返回值:
- 成功:0,失败:返回-1。
3.监听连接请求
// 给监听的套接字设置监听 int listen(int sockfd, int backlog);
参数:
sockfd:套接字的文件描述符,通过socket调用得到的返回值。backlog:在进入队列中等待接受的最大连接数,最大值为128。返回值:
- 成功:0,失败:返回-1。
4.接受连接
// 等待并接受客户端的连接请求, 建立新的连接, 会得到一个新的文件描述符(通信的) int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
sockfd:套接字的文件描述符。addr:用于存储客户端地址信息的结构体。addrlen:addr结构体的大小。返回值:
- 函数调用成功,得到一个文件描述符, 用于和建立连接的这个客户端通信,调用失败返回 -1。
这个函数是一个阻塞函数,当没有新的客户端连接请求的时候,该函数阻塞;当检测到有新的客户端连接请求时,阻塞解除,新连接就建立了,得到的返回值也是一个文件描述符,基于这个文件描述符就可以和客户端通信了。
5. 连接到服务器
// 成功连接服务器之后, 客户端会自动随机绑定一个端口 // 服务器端调用accept()的函数, 第二个参数存储的就是客户端的IP和端口信息 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
sockfd:套接字的文件描述符,通过socket调用得到的返回值。addr:用于存储客户端地址信息的结构体,这个IP和端口也需要转换为大端然后再赋值。addrlen:addr结构体的大小。返回值:
- 连接成功返回0,连接失败返回-1
6. 发送数据
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数:
sockfd:套接字的文件描述符。buf:包含要发送数据的缓冲区。len:要发送的数据的长度。flags:发送标志,通常为0。返回值:
- 成功:返回发送的字节数。
- 失败:返回-1。
7. 接收数据
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数:
sockfd:套接字的文件描述符。buf:用于接收数据的缓冲区。len:要接收的数据的长度。flags:接收标志,通常为0。返回值:
- 成功:返回接收的字节数。
- 失败:返回-1。
8.关闭套接字
int close(int sockfd);
参数:
sockfd:套接字的文件描述符。返回值:
- 成功:0,失败:返回-1。
服务器端通信流程
1.创建套接字: 使用
socket函数创建一个套接字,指定协议族(通常是AF_INET表示IPv4)、套接字类型(SOCK_STREAM表示TCP流套接字)、协议(通常为0,表示自动选择协议)。int server_socket = socket(AF_INET, SOCK_STREAM, 0);2.绑定地址: 使用
bind函数将套接字与特定的IP地址和端口号绑定。struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(8888); server_address.sin_addr.s_addr = INADDR_ANY;bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address));3.监听连接请求: 使用
listen函数开始监听连接请求。listen(server_socket, 5); // 允许最多5个连接请求排队4.接受连接: 使用
accept函数接受客户端的连接请求,该函数会阻塞程序直到有客户端连接进来。int client_socket = accept(server_socket, NULL, NULL);5.进行数据交互: 使用
send和recv函数进行数据的发送和接收。char buffer[1024]; recv(client_socket, buffer, sizeof(buffer), 0); send(client_socket, "Hello from server", strlen("Hello from server"), 0);6.关闭套接字: 使用
close函数关闭服务端的套接字。close(server_socket);示例代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h>int main() {// 1.创建监听的套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd == -1){perror("socket");return -1;}// 2.绑定本地的IP portstruct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY; // INADD_ANY自动读取本地的ip地址int ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));if (ret == -1){perror("bind");return -1;}// 3.设置监听ret = listen(fd, 128);if (ret == -1){perror("listen");return -1;}// 4.阻塞并等待客户端的连接struct sockaddr_in caddr;int addrlen = sizeof(caddr);int cfd = accept(fd, (struct sockaddr *)&caddr, &addrlen);if (cfd == -1){perror("accept");return -1;}// 连接建立成功,打印客户端的ip和端口信息char ip[32];printf("客户端的ip:%s,端口:%d\n", inet_ntop(AF_INET, &caddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(caddr.sin_port));// 5.通信while (1){ // 接受数据char buff[1024];int len = recv(cfd, buff, sizeof(buff), 0);if (len > 0){printf("client say:%s\n", buff);send(cfd, buff, len, 0);}else if (len == 0){printf("客户端已经断开了连接...\n");break;}else{perror("recv");break;}}close(fd);return 0; }
客户端通信流程
1.创建套接字: 使用
socket函数创建一个套接字。int client_socket = socket(AF_INET, SOCK_STREAM, 0);2.设置服务器地址: 设置服务器的地址信息,包括协议族、IP地址和端口号。
struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_port = htons(8888); server_address.sin_addr.s_addr = inet_addr("127.0.0.1");3.连接服务器: 使用
connect函数连接到服务器。connect(client_socket, (struct sockaddr *)&server_address, sizeof(server_address));4.进行数据交互: 使用
send和recv函数进行数据的发送和接收。char buffer[1024]; send(client_socket, "Hello from client", strlen("Hello from client"), 0); recv(client_socket, buffer, sizeof(buffer), 0);5.关闭套接字: 使用
close函数关闭客户端的套接字。close(client_socket);代码示例
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h>int main() {// 1.创建通信的套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd == -1){perror("socket");return -1;}// 2.连接服务器的IP portstruct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(9999);inet_pton(AF_INET, "192.168.3.128", &saddr.sin_addr.s_addr);int ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));if (ret == -1){perror("connect");return -1;}int number = 0;// 3.通信while (1){ // 发送数据char buff[1024];sprintf(buff, "你好,hello,world,%d...\n", number++);send(fd, buff, sizeof(buff), 0);// 接收数据memset(buff, 0, sizeof(buff));int len = recv(fd, buff, sizeof(buff), 0);if (len > 0){printf("server say:%s\n", buff);}else if (len == 0){printf("服务器端已经断开了连接...\n");break;}else{perror("recv");break;}sleep(1);}// 关闭文件描述符close(fd);return 0; }
相关文章:
102.套接字-Socket网络编程4(TCP通信流程)
目录 TCP编程流程 套接字函数 1.创建套接字 2.绑定地址 3.监听连接请求 4.接受连接 5. 连接到服务器 6. 发送数据 7. 接收数据 8.关闭套接字 服务器端通信流程 示例代码 客户端通信流程 代码示例 TCP编程流程 TCP是一个面向连接的,安全的,流…...
spring boot 2 升级到 spring boot 3 后文件上传失败
背景 项目需要,要求升级 spring boot 2.7 到 spring boot 3.2,升级过程中发现很多不兼容问题,下面说明文件上传失败的解决方案。 问题 spring boot 2 中不需要额外的配置,直接在 Controller 中配置 MultipartFile 接收页面传的…...
Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异,并取出不同的对象
Java Stream API 提供了一种非常方便的方式来比较两个 List 的差异,并取出不同的对象。这可以通过使用 distinct() 和 filter() 方法来实现。 假设我们有两个 List,一个是 list1,另一个是 list2,我们想找出 list1 中存在但 list2…...
C语言还会存在多久
一、C语言的生命力 在当前的科技发展和就业市场需求下,可以肯定地说C语言并没有像一些新兴语言(如Python、JavaScript等)那样受到大量的关注。然而,并不意味着学习C语言的人会越来越少。 首先,C语言作为一种深受尊重…...
手持式安卓主板_PDA安卓板_智能手持终端方案
手持式安卓主板方案是一种智能终端设备,具备自动对焦和闪光灯功能,可以在昏暗的环境下快速扫描二维码并轻松采集数据。该方案还提供多渠道支付和数据采集功能,为用户提供了便捷的体验。 该方案的产品基于手持式安卓主板,并搭载了八…...
LeetCode103. Binary Tree Zigzag Level Order Traversal
文章目录 一、题目二、题解 一、题目 Given the root of a binary tree, return the zigzag level order traversal of its nodes’ values. (i.e., from left to right, then right to left for the next level and alternate between). Example 1: Input: root [3,9,20,n…...
PHP 判断给定两个时间是否在同一周,月,年
判断是否在同一周 date_default_timezone_set(PRC); //判断是否在同一周,原理:求出其中一个时间戳所在周的周一凌晨时间戳和周日24.00时间戳,如果另一个时间戳在这个范围内,则说明在同一周,否则不在同一周 function g…...
单机无锁线程安全队列-Disruptor
Disruptor 1、基本介绍 说到队列,除了常见的mq中间件,java中也自带线程安全的BlockingQueue,但是BlockingQueue通过在入队和出队时加锁的方式避免并发操作,性能上会大打折扣。 而Disruptor是一个线程安全、低延迟、吞吐量高的队…...
好工具知多少:国内外最常用的SCADA软件
随着现代SCADA系统的发展,工业自动化取得了巨大的飞跃。如今,监控和数据采集(SCADA)系统已成为工业过程的重要组成部分。这些系统使操作员能够实时监控和控制复杂的系统。 SCADA系统正在广泛的行业中发挥着至关重要的作用&#x…...
SQL Server 2016(创建数据库)
1、实验环境。 某公司有一台已经安装了SQL Server 2016的服务器,现在需要新建数据库。 2、需求描述。 创建一个名为"db_class"的数据库,数据文件和日志文件初始大小设置为10MB,启用自动增长,数据库文件存放路径为C:\db…...
Vue学习计划--Vue2(一)简单了解vue
Vue2的终止支持时间为2023年12月31日。 在这个矛盾的时间点,还是决定先把vue2的笔记放出来,在Vue2完结后再把Vue3的笔记补上。这样呢,2和3都不落下,也算是来一个启承的作用吧。在工作中呢,旧的项目可以维护,…...
微信小程序生成二维码并保存到本地方法
微信小程序生成二维码请保存到本地方法 官方weapp-qrcode插件 github链接 功能完成样子 wxml <view class"qrcode"><canvas style"width: 275px; height: 275px;" canvas-idmyQrcode></canvas> </view> <view class" …...
shell_exec 和 exec区别
shell_exec 和 exec 都是用于在 PHP 中执行系统命令的函数,但它们之间有一些区别。 返回值类型:shell_exec 函数返回命令的输出结果作为字符串,而 exec 函数将输出结果存储在数组中。 输出结果:shell_exec 函数返回命令的完整输出…...
WPF创建进度条
使用wpf做一个原生的进度条,进度条上面有值,先看效果。 功能就是点击按钮,后台处理数据,前台显示处理数据的变化,当然还可以对进度条进行美化和关闭的操作,等待后台处理完毕数据,然后自动关闭。…...
全网最新最全面的Appium自动化:Appium常用操作之混合应用webview页面操作--待补充!
上下文操作: 在appium中,对于混合应用,需要进行WebView页面和原生应用的切换 常用的方法如下: 1、context(self) / current_context(self):返回当前会话的当前上下文,context可以理解为可进入的窗口。对于…...
基于OpenCV+YOLOv5实现车辆跟踪与计数(附源码)
导 读 本文主要介绍基于OpenCVYOLOv5实现车辆跟踪与计数的应用,并给出源码。 资源下载 基础代码和视频下载地址: https://github.com/freedomwebtech/win11vehiclecount main.py代码: import cv2import torchimport numpy as npfrom tr…...
05、pytest断言确定的异常
官方用例 # content of test_sysexit.py import pytestdef f():raise SystemExit(1)def test_mytest():with pytest.raises(SystemExit):f()解读与实操 标准python raise函数可产生异常。pytest.raises可以断言某个异常会发现。异常发生了,用例执行成功&#x…...
金蝶云星空单据编辑界面,不允许批量填充操作
文章目录 金蝶云星空单据编辑界面,不允许批量填充操作案例演示开发设计测试 金蝶云星空单据编辑界面,不允许批量填充操作 案例演示 售后单,明细信息单据体,物料编码字段禁止批量填充。 开发设计 编写表单插件,在Be…...
Springboot项目启动成功后可通过五种方式继续执行
实现CommandLineRunner接口 项目初始化完毕后,才会调用方法,提供服务 Component public class StartRunner implements CommandLineRunner {Overridepublic void run(String... args) throws Exception {System.out.println("CommandLineRunner&qu…...
什么是供应链金融分账系统?
一、供应链金融的重要性 供应链金融在很多行业都是要用到,比如在抖音,快手店铺的商家资金回笼,通常需要7-21天的回款周期,这对于商家的周转来说是一件很困难的事情,在供应链金融中,分账就扮演着至关重要的角色,不仅是金融流程中的一环,更是保…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
