TCP网络编程概述、相关函数、及实现超详解
文章目录
- TCP网络编程概述
- 1. TCP协议的特点
- 2. TCP与UDP的差异
- 3. TCP编程流程
- TCP网络编程相关函数详解
- 1. `socket()`:创建套接字
- 参数说明:
- 返回值:
- 示例:
- 2. `connect()`:客户端连接服务器
- 参数说明:
- 返回值:
- 示例:
- 3. `bind()`:服务器绑定地址和端口
- 参数说明:
- 返回值:
- 示例:
- 4. `listen()`:监听连接请求
- 参数说明:
- 返回值:
- 示例:
- 5. `accept()`:接受客户端连接
- 参数说明:
- 返回值:
- 示例:
- 6. `send()`:发送数据
- 参数说明:
- 返回值:
- 示例:
- 7. `recv()`:接收数据
- 参数说明:
- 返回值:
- 示例:
- 8. `close()`:关闭连接
- 参数说明:
- 返回值:
- 示例:
- TCP客户端与服务端的实现案例
- TCP客户端实现
- TCP服务器实现
TCP网络编程概述
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的传输层协议,广泛应用于网络通信。与UDP(User Datagram Protocol,用户数据报协议)不同,TCP提供了可靠的数据传输机制,确保数据能够完整、有序地从发送端传输到接收端。本文将详细介绍TCP协议的特点、TCP与UDP的差异、TCP编程流程以及客户端和服务器的实现方式。
1. TCP协议的特点
TCP具有以下主要特点:
- 面向连接:在通信前,TCP必须先建立连接。
- 有序号和确认机制:每个数据包都带有序号,接收方需要发送确认序号,确保数据有序接收。
- 排序、检错和失败重传:TCP对接收到的数据进行排序,检查数据的完整性,如有错误,会进行重传。
- 大文件传输:由于TCP能够分片并重新组装数据包,它特别适合大文件的可靠传输。
- 不支持广播和多播:与UDP不同,TCP不支持广播和多播,只支持点对点通信。
在TCP通信中,客户端和服务器的角色各不相同:
- TCP客户端:主动向服务器发起连接。
- TCP服务器:被动等待客户端连接。
2. TCP与UDP的差异
| 特点 | TCP | UDP |
|---|---|---|
| 面向连接 | 是 | 否 |
| 可靠传输 | 是 | 否 |
| 顺序保证 | 是 | 否 |
| 传输效率 | 较低(需要连接、确认等) | 较高(无连接、无确认) |
| 数据传输大小限制 | 无 | 有(单个数据包有限制) |
| 广播/多播支持 | 否 | 是 |
TCP更适合需要可靠传输的应用场景,如文件传输、邮件等,而UDP更适合实时性要求高的应用,如视频、语音传输。
3. TCP编程流程
编写TCP程序时,主要流程如下:
- 创建套接字:使用
socket()函数创建TCP套接字。 - 连接服务器(客户端)或绑定端口并监听连接(服务器)。
- 发送或接收数据:通过
send()和recv()函数进行数据交换。 - 关闭连接:使用
close()函数关闭套接字。

TCP网络编程相关函数详解
在编写TCP程序时,通常会使用一系列网络函数来创建套接字、建立连接、发送/接收数据并关闭连接。下面将对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,表示使用默认协议(TCP或UDP)。
返回值:
- 成功:返回套接字的文件描述符。
- 失败:返回-1,并设置
errno。
示例:
int sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
if (sock < 0) {perror("socket creation failed");
}
2. connect():客户端连接服务器
connect()函数用于客户端主动向服务器发起连接请求。在TCP连接中,客户端通过该函数连接指定的服务器。
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明:
sockfd:客户端套接字描述符。addr:服务器的地址结构,通常为struct sockaddr_in。addrlen:地址结构的大小。
返回值:
- 成功:返回0。
- 失败:返回-1,并设置
errno。
示例:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8000); // 服务器端口号
server_addr.sin_addr.s_addr = inet_addr("10.35.184.221"); // 服务器IP地址if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {perror("connect failed");
}
3. bind():服务器绑定地址和端口
bind()函数用于将套接字绑定到指定的IP地址和端口号。服务器需要通过bind()来指定其服务的地址和端口。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明:
sockfd:服务器套接字描述符。addr:服务器地址结构,通常为struct sockaddr_in。addrlen:地址结构的大小。
返回值:
- 成功:返回0。
- 失败:返回-1,并设置
errno。
示例:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9000); // 绑定端口9000
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定本机所有IPif (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {perror("bind failed");
}
4. listen():监听连接请求
服务器通过listen()函数来监听客户端的连接请求,进入监听状态,准备接受客户端的连接。
int listen(int sockfd, int backlog);
参数说明:
sockfd:服务器套接字描述符。backlog:连接队列的大小,表示服务器可以处理的等待连接的客户端数量。
返回值:
- 成功:返回0。
- 失败:返回-1,并设置
errno。
示例:
if (listen(sock, 5) != 0) { // 最大连接等待队列长度为5perror("listen failed");
}
5. accept():接受客户端连接
accept()函数用于服务器从连接队列中取出一个客户端连接,生成一个新的套接字,用于和该客户端进行通信。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数说明:
sockfd:服务器监听套接字。addr:客户端地址结构,用于存储连接的客户端信息。addrlen:地址结构的大小。
返回值:
- 成功:返回一个新的已连接套接字描述符,用于与客户端通信。
- 失败:返回-1,并设置
errno。
示例:
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_sock = accept(sock, (struct sockaddr *)&client_addr, &client_len);
if (client_sock < 0) {perror("accept failed");
}
6. send():发送数据
send()函数用于向指定的套接字发送数据。
ssize_t send(int sockfd, const void *buffer, size_t length, int flags);
参数说明:
sockfd:套接字描述符。buffer:指向需要发送数据的缓冲区。length:要发送的数据长度。flags:通常为0,可选其他标志位。
返回值:
- 成功:返回发送的字节数。
- 失败:返回-1,并设置
errno。
示例:
char message[] = "Hello, TCP Server!";
if (send(sock, message, strlen(message), 0) < 0) {perror("send failed");
}
7. recv():接收数据
recv()函数用于从指定的套接字接收数据。
ssize_t recv(int sockfd, void *buffer, size_t length, int flags);
参数说明:
sockfd:套接字描述符。buffer:指向接收数据的缓冲区。length:缓冲区大小。flags:通常为0,可选其他标志位。
返回值:
- 成功:返回接收到的字节数。
- 失败:返回-1,并设置
errno。 - 如果连接被关闭,返回0。
示例:
char buffer[128];
ssize_t bytes_received = recv(sock, buffer, sizeof(buffer), 0);
if (bytes_received > 0) {buffer[bytes_received] = '\0'; // 确保数据是以字符串形式输出printf("Received data: %s\n", buffer);
} else if (bytes_received == 0) {printf("Connection closed by peer\n");
} else {perror("recv failed");
}
8. close():关闭连接
close()函数用于关闭指定的套接字,释放相关资源。
int close(int sockfd);
参数说明:
sockfd:需要关闭的套接字描述符。
返回值:
- 成功:返回0。
- 失败:返回-1,并设置
errno。
示例:
close(sock); // 关闭套接字
TCP客户端与服务端的实现案例
TCP客户端实现
在TCP客户端编程中,客户端主动发起与服务器的连接。以下是一个基本的TCP客户端代码示例:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>typedef struct sockaddr_in addr_in;
typedef struct sockaddr addr;int main(int argc, char const *argv[]) {// 创建TCP套接字int sock = socket(AF_INET, SOCK_STREAM, 0);// 连接TCP服务器addr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8000);server_addr.sin_addr.s_addr = inet_addr("10.35.184.221");if (connect(sock, (addr *)&server_addr, sizeof(server_addr)) != 0) {perror("connect");return -1;}printf("TCP server connect OK\n");// 每2秒发送一次数据int n = 0;while (1) {char data[] = "hi, tcp server!";if (send(sock, data, strlen(data), 0) > 0) {printf("(%d)发送成功!\n", ++n);}sleep(2);}close(sock);return 0;
}
TCP服务器实现
TCP服务器是被动的,等待客户端连接。在实现中,服务器需要首先绑定地址并监听客户端连接,接着通过accept()函数接受客户端的连接。以下是一个简单的单聊TCP服务器实现:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>typedef struct sockaddr_in addr_in;
typedef struct sockaddr addr;typedef struct {int sock;char ip[INET_ADDRSTRLEN];
} client_info;void *readTask(void *arg) {client_info *info = (client_info *)arg;while (1) {char buf[128] = "";ssize_t len = recv(info->sock, buf, 128, 0);if (len > 0) {printf("%s: %s\n", info->ip, buf);}}
}void *sendTask(void *arg) {client_info *info = (client_info *)arg;while (1) {char buf[128] = "";fgets(buf, 128, stdin);buf[strlen(buf)-1] = 0;send(info->sock, buf, strlen(buf), 0);if (strncmp(buf, "bye", 3) == 0) break;}
}int main(int argc, char const *argv[]) {if (argc != 2) return -1;// 创建TCP套接字int sock = socket(AF_INET, SOCK_STREAM, 0);// 设置服务器地址addr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(atoi(argv[1]));server_addr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(sock, (addr *)&server_addr, sizeof(server_addr)) != 0) {perror("bind");return -1;}listen(sock, 1000);printf("TCP server running\n");addr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);int client_sock = accept(sock, (addr *)&client_addr, &client_addr_len);if (client_sock > 0) {client_info info;info.sock = client_sock;inet_ntop(AF_INET, &client_addr.sin_addr, info.ip, INET_ADDRSTRLEN);printf("Client connected: %s\n", info.ip);pthread_t read_tid, send_tid;pthread_create(&read_tid, NULL, readTask, &info);pthread_create(&send_tid, NULL, sendTask, &info);pthread_join(send_tid, NULL);}close(sock);return 0;
}
通过上述TCP网络编程的介绍和实例代码,读者可以掌握如何使用TCP协议进行可靠的数据通信,并根据实际需求实现功能丰富的网络应用程序。
相关文章:
TCP网络编程概述、相关函数、及实现超详解
文章目录 TCP网络编程概述1. TCP协议的特点2. TCP与UDP的差异3. TCP编程流程 TCP网络编程相关函数详解1. socket():创建套接字参数说明:返回值:示例: 2. connect():客户端连接服务器参数说明:返回值&#x…...
Cluade 3.5 Sonnet 提示词泄露
prompt 翻译: The notebook currently demonstrates support for a two agent setup. Support for GroupChat is currently in development....
git clone代码报错Permission denied (publickey)
git clone gerrit SSH的Clone with commit-msg hook代码连接,报错Permission denied (publickey). 一般在C:\Users\用户名.ssh文件夹下有一个id_rsa.pub文件 把文件里的内容复制 到gerrit网站上User Settings的SSH keys里 在New SSH key里粘贴刚刚复制的内容&…...
QT设计中文输入法软键盘DLL给到C#开发步骤
开发目的:本文提供解决触摸屏C#程序中无法输入中文问题,中文拼音采用开源的谷歌输入法程序、使用QT编译中文输入法界面和中文输入法接口给到C#使用。 开发步骤: 1、QT中设计字母和字符输入界面 2、QT中设计数字输入界面 3、QT中封装调用谷歌…...
使用 Rust 和 wasm-pack 开发 WebAssembly 应用
一、什么是 WebAssembly? WebAssembly 是一种运行在现代 Web 浏览器中的新型二进制指令格式。它是一种低级别的字节码,可以被多种语言编译,并在浏览器中高效运行。 1.1 WebAssembly 的背景与概念 高性能计算:WebAssembly 旨在提…...
1. IP地址介绍
IP地址 一、网络概述1、网络类型2、网络组成、传输介质2.1 组成2.2 传输介质 二、IP地址1、IP地址的表示方法2、IP地址的组成3、IP地址的类型3.1 根据IP地址第一个字节大小来分3.1.1 单播地址 Unicast 3.2 根据IP地址的使用 三、子网掩码 netmask1、默认的子网掩码2、判断多个I…...
喜报来袭~又有一波优秀企业选择Smartbi
近期,大金(中国)武汉&广州分公司、中广核智能、新疆银行、四川省人民医院等多家知名企业/机构签约Smartbi,数智化建设再上新高度! Smartbi数10年专注于商业智能BI与大数据分析软件与服务,为各行各业提…...
Web端云剪辑解决方案,BS架构私有化部署,安全可控
传统视频制作流程繁琐、耗时,且对专业设备和软件的高度依赖,常常让企业望而却步,美摄科技凭借其强大的技术实力和创新能力,推出了面向企业用户的Web端云剪辑解决方案,为企业提供一站式、高效、便捷的视频生产平台。 B…...
AI 代码助手插件推荐
AI正在重塑我们的工作方式,软件开发也不例外。AI编码助手使开发人员能够比以往更快、更有效地编写代码。 在本文中,我们将比较几个个最好的AI编码助手,突出它们的独特功能和价格,以帮助读者找到完美的编码伙伴: 1、腾讯云 AI 代…...
word中的表格全部设置宽度100%
1、背景 我们用工具将数据库或其他的数据导出成word时,表格有的会大于100%,超过了边界。word没有提供全局修改的方法。如果我们想改成100%。 一种方式是通过宏,全局改。一种是手动改。 2、宏修改 如果表格多,可以通过这种方式。…...
JFinal整合Websocket
学习笔记,供大家参考 总结的不错的话,记得点赞收藏关注哦!导入JAR包 javax.websocket-api <dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1&…...
(done) 声音信号处理基础知识(7) (Understanding Time Domain Audio Features)
参考:https://www.youtube.com/watch?vSRrQ_v-OOSg&t1s 时域特征包括: 1.幅度包络 2.均方根能量 3.过零率 振幅包络的定义:一个 frame 里,所有采样点中最大的振幅值 一个形象的关于振幅包络的可视化解释如下:…...
拓数派荣获上海数据交易所“数据治理服务商”认证
近期,杭州拓数派科技发展有限公司(以下简称“拓数派”)荣获上海数据交易所“数据治理服务商”认证,标志着拓数派正式加入上海数据交易所数商生态,成为上海数据交易所官方认证的数据治理服务商。拓数派企业发展部总监吴…...
【Redis】分布式锁之 Redission
一、基于setnx实现的分布式锁问题 重入问题:获得锁的线程应能再次进入相同锁的代码块,可重入锁能防止死锁。例如在HashTable中,方法用synchronized修饰,若在一个方法内调用另一个方法,不可重入会导致死锁。而synchroni…...
对象序列化
Data AllArgsConstructor NoArgsConstructor public class Product implements Serializable {public Long productId;public String productName;public Double productPrice;public String productImg;public Integer productStatus;public String productCategory; }为什么要…...
什么是专利开放许可?
专利作为技术创新的重要载体,其有效转化与应用成为推动社会进步和经济发展的关键力量。那么,专利开放许可究竟是何方神圣?它如何打破传统专利许可的壁垒,促进创新资源的广泛共享? 专利开放许可的定义 专利开放许可&am…...
地表最强开源大模型!Llama 3.2,如何让你的手机变身私人智能助理
你有没有想过,为什么现在的手机越来越像小型电脑?无论是拍照、看视频,还是用各种APP,甚至是AI助手,手机的功能几乎无所不能。其实,这一切的背后有一个技术正在悄悄改变我们的生活,那就是Llama 3…...
Pandas中DataFrame表格型数据结构
目录 1、DataFrame是什么2、创建一个dataframe3、获取dataframe的行、列索引4、获取dataframe的值 1、DataFrame是什么 series是有一组数据与一组索引(行索引)组成的数据结构,而dataframe是由一组数据与一对索引(行索引和列索引&…...
C++的智能指针
很久之前,我们说到了new和delete关键字。 new在堆上分配内存,需要delete来删除内存、释放内存,因为它不会自动释放内存。 智能指针是实现过程自动化的一种方式,即当我们调用new时,我们不需要调用delete关键字。 在很…...
微信小程序showLoading ,showToast ,hideLoading连续调用出现showLoading 不关闭的情况记录
wx.showLoading({title: "操作中",mask: true,});api().then(() > {wx.showToast({title: "操作成功",icon: "none",});}).finally(() > {wx.hideLoading();}); 类似的代码偶尔会出现showLoading不关闭的现象, 这种情况下的解决方法就是 …...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
