当前位置: 首页 > news >正文

TCP和UDP通信基础

目录

1. 套接字 (Socket)

2. 基于TCP通信的流程

服务器端

客户端

1. TCP通信API

1.1 创建套接字描述符socket

1.2 绑定IP和端口号bind

1.3 设置监听状态 listen

1.4 接受连接请求 accept

1.5 发送数据 send

1.6 接收数据 recv

2. TCP服务器代码示例

代码解释:

注意点:

 3. 客户端API

连接服务器

功能:

参数说明:

返回值:

示例:

代码解释:

注意事项:


1. 套接字 (Socket)

  1. 套接字的本质

    • socket套接字是一个特殊的文件,在原始Linux中,它与管道、消息队列、共享内存、信号等机制类似,只能用于主机内的进程间通信。
  2. 历史发展与通信范围

    • 随着TCP/IP协议族的出现,socket套接字能够通过网卡,与外部主机进行通信,突破了单机限制。
  3. socket函数的作用

    • 调用socket函数会生成一个文件描述符。
    • 主机间的不同进程可以通过对该文件描述符的读写,实现通信。


2. 基于TCP通信的流程

服务器端

  1. socket

    • 创建原始套接字。

  2. bind

    • 将原始套接字与主机IP绑定(该服务器的身份,服务器以字节主机的身份通信)。
      • 通过bind,服务器的套接字被绑定到一个明确的IP地址和端口号。
      • 当客户端发起通信请求时,客户端通过这个IP地址和端口号找到服务器,从而使服务器在网络中以“唯一身份”进行通信。
  3. listen

    • 将原始套接字设置为监听状态。
    • 注意:监听套接字只能用于监听,要进行实际通信需要创建一个新的套接字。
  4. accept

    • 接收客户端的连接请求,获取客户端信息,并生成一个新的套接字描述符,用于与该客户端通信。
  5. 通信与关闭

    • 使用新套接字发送和接收信息。
    • 完成通信后关闭套接字。

客户端

  1. socket

    • 创建原始套接字。
  2. bind(可选)

    • 客户端可以选择是否绑定IP和端口号。
    • 如果绑定,则客户端只能以绑定的IP和端口号进行通信。通常情况下无需绑定,除非服务器要求接收特定客户端的信息。
  3. connect

    • 向服务器发送连接请求,并携带客户端的身份信息(IP和端口号)。
  4. 通信与关闭

    • 通过套接字发送和接收信息。
    • 完成通信后关闭套接字。

1. TCP通信API

1.1 创建套接字描述符socket
#include <sys/types.h>          
#include <sys/socket.h>int socket(int domain, int type, int protocol);
  • 功能:创建一个套接字描述符。
  • 参数
    • domain:通信域类型
      • AF_UNIX, AF_LOCAL: 本地通信
      • AF_INET: IPv4通信
      • AF_INET6: IPv6通信
    • type:通信类型
      • SOCK_STREAM: 使用TCP通信协议
      • SOCK_DGRAM: 使用UDP通信协议
    • protocol:通常为0,表示自动选择与domaintype兼容的协议。
  • 返回值:成功返回套接字描述符,失败返回-1。

1.2 绑定IP和端口号bind
#include <sys/types.h>
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

  • 功能:将套接字与IP和端口绑定,指定通信域。
  • 参数
    • sockfd:套接字文件描述符。
    • addr:通信域的结构体指针,通常是struct sockaddr_in,其中包含IP地址和端口号。
    • addrlen:结构体的大小。
  • 返回值:成功返回0,失败返回-1。

1.3 设置监听状态 listen
#include <sys/types.h>
#include <sys/socket.h>int listen(int sockfd, int backlog);
  • 功能:设置套接字为监听状态,等待客户端连接。
  • 参数
    • sockfd:套接字描述符。
    • backlog:最大等待连接数,最多为128。
  • 返回值:成功返回0,失败返回-1。

1.4 接受连接请求 accept
#include <sys/types.h>
#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 功能:从监听队列中接受客户端连接,创建新的套接字用于通信。
  • 参数
    • sockfd:监听套接字描述符。
    • addr:客户端信息结构体(struct sockaddr_in),接受客户端信息。
    • addrlen:客户端信息结构体的大小。
  • 返回值:成功返回新套接字描述符,失败返回-1。

1.5 发送数据 send
#include <sys/types.h>
#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);
  • 功能:向其他进程发送数据。
  • 参数
    • sockfd:新套接字文件描述符。
    • buf:发送的数据缓冲区。
    • len:发送的数据长度。
    • flags:控制发送的标志(例如MSG_DONTWAIT表示非阻塞发送)。
  • 返回值:成功返回发送的字节数,失败返回-1。

1.6 接收数据 recv
#include <sys/types.h>
#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t len, int flags);
  • 功能:从其他进程接收数据。
  • 参数
    • sockfd:新套接字文件描述符。
    • buf:接收数据的缓冲区。
    • len:接收数据的最大长度。
    • flags:控制接收的标志(例如MSG_DONTWAIT表示非阻塞接收)。
  • 返回值:成功返回接收的字节数,失败返回-1。

2. TCP服务器代码示例

#include <myhead.h>
#define IP "192.168.60.69"
#define PORT 6666
#define BACKLOG 20int main(int argc, const char *argv[])
{// AF_INET: IPV4通信// SOCK_STREAM:TCP通信协议int oldfd = socket(AF_INET, SOCK_STREAM, 0); // 1. 创建套接字if (oldfd == -1){perror("socket");return -1;}// 2. 绑定IP和端口号struct sockaddr_in server = {.sin_family = AF_INET,          // IPV4.sin_port = htons(PORT),        // 端口号转为网络字节序.sin_addr.s_addr = inet_addr(IP), // IP地址};if (bind(oldfd, (struct sockaddr *)&server, sizeof(server)) == -1){perror("bind");return -1;}// 3. 监听if (listen(oldfd, BACKLOG) == -1){perror("listen");return -1;}// 4. 接受客户端连接请求,创建新的描述符用于通信struct sockaddr_in client; // 接收客户端信息的结构体socklen_t client_len = sizeof(client); // 计算出结构体大小int newfd;newfd = accept(oldfd, (struct sockaddr *)&client, &client_len);if (newfd == -1){perror("accept");return -1;}printf("%s发来连接请求\n", inet_ntoa(client.sin_addr));// 5. 循环收发信息char buff[1024];while (1){memset(buff, 0, sizeof(buff));// int len = read(newfd, buff, sizeof(buff)); // 传统方式int len = recv(newfd, buff, sizeof(buff), 0); // 0: 阻塞发送,MSG_DONTWAIT: 非阻塞if (len == 0){printf("客户端下线\n");break;}printf("%s\n", buff);strcat(buff, "5201314"); // 加上一句话回过去// write(newfd, buff, sizeof(buff)); // 传统方式send(newfd, buff, sizeof(buff), 0); // 发送}close(oldfd);close(newfd);return 0;
}
代码解释:
  1. 创建套接字socket(AF_INET, SOCK_STREAM, 0) 创建一个支持 IPv4 的 TCP 套接字。
  2. 绑定 IP 和端口:通过 bind 函数将服务器的 IP 地址和端口号绑定到创建的套接字上。
  3. 监听:调用 listen 函数将套接字设置为监听状态,BACKLOG 指定了等待连接队列的最大长度。
  4. 接受客户端连接accept 函数用于从等待队列中接收客户端的连接请求,返回一个新的套接字文件描述符用于与客户端进行通信。
  5. 收发信息:使用 recv 接收客户端发来的信息,并通过 send 发送响应。消息中添加了 "5201314" 字符串后回传给客户端。
  6. 关闭套接字:完成通信后,通过 close 关闭原始套接字和客户端套接字。
注意点:
  • recvsend 用于数据传输,它们是基于 TCP 协议的,保证数据的可靠传输。
  • inet_ntoa 函数用于将客户端的 IP 地址转换为点分十进制格式。
  • 使用 strcat 拼接字符串发送回客户端。

 3. 客户端API

连接服务器
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

功能:
  • connect 用于客户端与服务器建立连接。它对应于服务器端的 accept 函数,完成了三次握手的过程。
  • 客户端通过调用 connect 向服务器发送连接请求,服务器通过 accept 接受连接。此时,TCP连接的三次握手完成。
参数说明:
  • 参数1 (sockfd):套接字描述符,即客户端通过 socket 函数创建的套接字。
  • 参数2 (addr):服务器的地址结构体,包含目标服务器的 IP 地址和端口号。
  • 参数3 (addrlen)addr 结构体的大小,用于指定服务器地址结构体的大小。
返回值:
  • 成功:返回 0。
  • 失败:返回 -1,并置位错误码。
示例:
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>#define SERVER_IP "192.168.60.69"
#define SERVER_PORT 6666int main() {int sockfd = socket(AF_INET, SOCK_STREAM, 0);  // 创建套接字if (sockfd == -1) {perror("socket");return -1;}struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;              // IPV4server_addr.sin_port = htons(SERVER_PORT);     // 服务器端口server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);  // 服务器IP// 连接到服务器if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {perror("connect");return -1;}printf("成功连接到服务器\n");// 这里可以添加发送和接收数据的代码close(sockfd);  // 关闭套接字return 0;
}

 

代码解释:
  1. 创建套接字:客户端使用 socket 函数创建一个 TCP 套接字。
  2. 填充服务器地址结构体struct sockaddr_in 用于定义目标服务器的 IP 地址和端口号。
  3. 建立连接:客户端调用 connect 函数连接到指定服务器。如果连接成功,将输出 "成功连接到服务器"
  4. 关闭套接字:连接完成后,使用 close 关闭套接字。
注意事项:
  • 连接过程中的三次握手是自动进行的,客户端不需要手动处理三次握手的细节。
  • 如果连接失败(例如服务器不可达或端口未打开),connect 将返回 -1,并设置相应的错误码。

相关文章:

TCP和UDP通信基础

目录 1. 套接字 (Socket) 2. 基于TCP通信的流程 服务器端 客户端 1. TCP通信API 1.1 创建套接字描述符socket 1.2 绑定IP和端口号bind 1.3 设置监听状态 listen 1.4 接受连接请求 accept 1.5 发送数据 send 1.6 接收数据 recv 2. TCP服务器代码示例 代码解释&…...

微服务中的技术使用与搭配:如何选择合适的工具构建高效的微服务架构

一、微服务架构中的关键技术 微服务架构涉及的技术非常广泛&#xff0c;涵盖了开发、部署、监控、安全等各个方面。以下是微服务架构中常用的一些技术及其作用&#xff1a; 1. 服务注册与发现 微服务架构的一个重要特性是各个服务是独立部署的&#xff0c;因此它们的地址&am…...

找出字符串第一个匹配项的下标

找出字符串第一个匹配项的下标 题目描述&#xff1a; 题解思路&#xff1a; 图上所示&#xff0c;利用字符滑动&#xff0c;如果匹配就字符开始移动&#xff1b;如果不匹配成功&#xff0c;则停止移动&#xff0c;并回到字符串刚开始匹配的字符下标前一个&#xff0c;为下一次…...

面向FWA市场!移远通信高性能5G-A模组RG650V-NA通过北美两大重要运营商认证

近日&#xff0c;全球领先的物联网整体解决方案供应商移远通信宣布&#xff0c;其旗下符合3GPP R17标准的新一代5G-A模组RG650V-NA成功通过了北美两家重要运营商认证。凭借高速度、大容量、低延迟、高可靠等优势&#xff0c;该模组可满足CPE、家庭/企业网关、移动热点、高清视频…...

Matlab实现北方苍鹰优化算法优化随机森林算法模型 (NGO-RF)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1内容介绍 北方苍鹰优化算法&#xff08;Northern Goshawk Optimization, NGO&#xff09;是一种新颖的群智能优化算法&#xff0c;灵感源自北方苍鹰捕食时的策略。该算法通过模拟苍鹰的搜寻、接近和捕捉猎物的行为模式&am…...

搭建环境 配置编译运行 mpi-test-suite

1&#xff0c;编译安装 ucx 下载源码&#xff1a; $ git clone https://github.com/openucx/ucx.git $ ​git checkout v1.17.0 ​ 运行auto工具&#xff1a; $ ./autogen.sh $ ./autogen.sh 指所以运行两次是因为有时候第一次会失败&#xff0c;原因未查。 配置 ucx $ m…...

夜神模拟器启动报错:虚拟机启动失败 请进行修复 关闭hyper-v

不是关闭hyper-v的问题。 点那个没用。 解决办法&#xff1a; 我电脑win11&#xff08;win10 win11都一样 &#xff09;去安全中心-设备安全性 把内存完整性关了。 这还不够。 在右上角找系统信息 我发现VT显示没开 于是我去BIOS中开启VT 这个VT怎么开很简单。就是你F2 F1…...

投资策略规划最优决策分析

目录 一、投资策略规划问题详细 二、存在最优投资策略&#xff1a;每年都将所有钱投入到单一投资产品中 &#xff08;一&#xff09;状态转移方程 &#xff08;二&#xff09;初始条件与最优策略 &#xff08;三&#xff09;证明最优策略总是将所有钱投入到单一投资产品中…...

一篇保姆式虚拟机安装ubantu教程

前言&#xff1a; 本文将介绍在VMware安装ubantu&#xff0c;会的人可以试试上一篇介绍centos/ubantu安装docker环境,不同环境安装docker。一篇保姆式centos/unbantu安装docker 官网下载iso:Ubuntu 18.04.6 LTS (Bionic Beaver) 本次使用的版本是&#xff1a; 一&…...

缓冲区的奥秘:解析数据交错的魔法

目录 一、理解缓存区的好处 &#xff08;一&#xff09;直观性的理解 &#xff08;二&#xff09;缓存区的好处 二、经典案例分析体会 &#xff08;一&#xff09;文件读写流&#xff08;File I/O Buffering&#xff09; BufferedOutputStream 和 BufferedWriter 可以加快…...

CentOS 7.9 搭建本地Yum源

yum&#xff08;Yellow Dog Updater&#xff0c;Modified&#xff09;是一个在Fedora、Centos、RedHat中的Shell前端软件包管理器。基于RPM包管理&#xff0c;能够从指定的服务器自动下载RPM包并且安装&#xff0c;可以自动处理依赖关系&#xff0c;并且一次安装所有依赖的软件…...

【Python】爬虫实战:高效爬取电影网站信息指南(涵盖了诸多学习内容)

本期目录 1 爬取思路 2 爬虫过程 2.1 网址 2.2 查看网页代码 3 爬取数据 3.1 导入包 3.2 爬取代码 01 爬取思路 \*- 第一步&#xff0c;获取页面内容\*- 第二步&#xff1a;解析并获取单个项目链接 \*- 第三步&#xff1a;获取子页面内容 \*- 第四步&#xff1a;解析…...

MATLAB和C++及Python流式细胞术

&#x1f335;MATLAB 片段 流式细胞术&#xff08;Flow Cytometry&#xff09;是一种用于分析细胞或其他颗粒悬浮在流动介质中的方法。MATLAB 可以用来处理和分析流式细胞术的数据&#xff0c;例如用于数据预处理、可视化和分析。以下是一些常见的 MATLAB 处理流式细胞术数据的…...

Vue3 pinia使用

Pinia 是一个现代的状态管理库&#xff0c;专为 Vue 3 设计。它提供了一种简单、直观的方式来管理应用中的全局状态 (就是不同组件都希望去共享的一些变量,函数等)。Pinia 的设计灵感来自于 Vuex&#xff08;Vue 2 的状态管理库&#xff09;&#xff0c;但进行了许多改进&#…...

tdengine学习笔记-建库和建表

目录 建库和建表 创建超级表​ 创建表​ 自动建表​ 创建普通表​ 多列模型 VS 单列模型​ 数据类型映射​ 示例程序汇总​ 在车联网领域的应用 1. 数据模型概述 2. 表结构设计 2.1 静态数据表 2.2 动态数据表 4. 查询数据 4.1 查询单个车辆的数据 4.2 查询多个…...

Django数据迁移出错,解决raise NodeNotFoundError问题

错误出现在&#xff1a; raise NodeNotFoundError(self.error_message, self.key, originself.origin) django.db.migrations.exceptions.NodeNotFoundError: Migration myApp.0003_alter_jobinfo_practise dependencies reference nonexistent parent node (myApp, 0002_renam…...

景联文科技:以全面数据处理服务推动AI创新与产业智能化转型

数据标注公司在人工智能领域扮演着重要角色&#xff0c;通过提供高质量的数据标注服务&#xff0c;帮助企业和组织训练和优化机器学习模型。从需求分析到数据交付&#xff0c;每一个步骤都需要严格把控&#xff0c;确保数据的质量和安全性。 景联文科技是一家专业的数据采集与标…...

MySQL学习/复习7表的内外连接

一、内连接...

Spring Cloud入门笔记2(OpenFeign)

场景&#xff1a; OpenFeign中集成了LoadBalancer,并简化了微服务调用&#xff0c;所以实际上使用该技术 技术栈&#xff1a;OpenFeign 步骤一&#xff1a;导入依赖 <!--openfeign--> <dependency><groupId>org.springframework.cloud</groupId><a…...

小程序中模拟发信息输入框,让textarea可以设置最大宽以及根据输入的内容自动变高的方式

<textarea show-confirm-bar"{{false}}" value"{{item.aValue}}" maxlength"301" placeholder"请输入" auto-height"{{true}}" bind:blur"onBlurTextarea" focus"{{true}}" bindinput"…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...