Linux网络编程:Socket套接字编程(Server服务器 Client客户端)
文章目录:
一:定义和流程分析
1.定义
2.流程分析
3.网络字节序
二:相关函数
IP地址转换函数inet_pton inet_ntop(本地字节序 网络字节序)
socket函数(创建一个套接字)
bind函数(给socket绑定一个服务器地址结构(IP+port))
listen函数(设置最大连接数或者说能同时进行三次握手的最大连接数监听上限)
accept函数(阻塞监听等待客户端建立连接, 成功的话返回一个与客户端成功连接的socket文件描述符)
connect函数(使用现有的socket与服务器建立连接)
三:服务器模型和客户端模型的实现
Server服务器的实现
Client客户端的实现
一:定义和流程分析
1.定义
定义:一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现)在通信过程中, 套接字一定是成对出现的一种文件类型,伪文件,不占用存储空间,可进行IO操作,可间接看做文件描述符使Socket本身有“插座”的意思在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件管道, 套接字, 块设备, 字符设备;套接字: 一个fd可以索引读写两个缓冲区;
2.流程分析
socket():创建一个套接字, 用fd索引bind():绑定IP和portlisten():设置监听上限(同时与Server建立连接数)accpet():阻塞监听客户端连接(传入一个上面创建的套接字, 传出一个连接的套接字)在客户端中的connect()中绑定IP和port,并建立连接(阻塞)
3.网络字节序
小端法:(pc本地存储) 高位存高地址。低位存低地址。 int a = 0x12345678 大端法:(网络存储) 高位存低地址。低位存高地址。htonl --> 本地--》 网络 (IP) 192.168.1.11 --> string --> atoi --> int --> htonl --> 网络字节序 htons --> 本地--》 网络 (port) ntohl --> 网络--》 本地(IP) ntohs --> 网络--》 本地(Port)用库函数做网络字节序和主机字节序的转换
#include<arpa/inet.h> uint32_t htonl(uint32_t hostlong); //主要针对IP uint16_t htons(uint16_t hostshort); //主要针对port uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);
二:相关函数
IP地址转换函数inet_pton inet_ntop(本地字节序 网络字节序)
由于如
192.168.45.2这种的IP地址为点分十进制表示,需要转化为uint32_t型,有现成的函数(IPv4和IPv6都可以转换)//本地字节序(string IP) ---> 网络字节序 int inet_pton(int af, const char *src, void *dst); af:AF_INET、AF_INET6src:传入,IP地址(点分十进制)dst:传出,转换后的 网络字节序的 IP地址。 返回值:成功: 1异常: 0, 说明src指向的不是一个有效的ip地址。失败:-1//网络字节序 ---> 本地字节序(string IP) const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); af:AF_INET、AF_INET6src: 网络字节序IP地址dst:本地字节序(string IP)size: dst 的大小。返回值: 成功:dst、失败:NULL
socket函数(创建一个套接字)
#include <sys/socket.h>int socket(int domain, int type, int protocol); 创建一个 套接字domain指定使用的协议(IPv4或IPv6)AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址AF_INET6 与上面类似,不过是来用IPv6的地址AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用type指定数据传输协议(流式或报式)SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。SOCK_SEQPACKET该协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。SOCK_RAW socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序指定代表协议(一般默认传0)protocol: 0 流式以TCP为代表;报式以UDP为代表;返回值:返回指向新创建的socket的文件描述符成功:返回新套接字所对应文件描述符fd失败:返回-1并设置errno;
bind函数(给socket绑定一个服务器地址结构(IP+port))
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 给socket绑定一个 地址结构 (IP+port)sockfd: socket文件描述符struct sockaddr_in servaddr;addr.sin_family = AF_INET;addr.sin_port = htons(8888);addr.sin_addr.s_addr = htonl(INADDR_ANY);addr: 构造出IP地址加端口号传入参数(struct sockaddr *)&addraddrlen: sizeof(addr) 地址结构的大小返回值:成功:0失败:返回-1, 设置errno
listen函数(设置最大连接数或者说能同时进行三次握手的最大连接数监听上限)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h>int listen(int sockfd, int backlog); //设置同时与服务器建立连接的上限数(同时进行3次握手的客户端数量)sockfd:socket文件描述符backlog:上限数值。最大值 128排队建立3次握手队列和刚刚建立3次握手队列的链接数和返回值:成功:0失败:-1 errno
accept函数(阻塞监听等待客户端建立连接, 成功的话返回一个与客户端成功连接的socket文件描述符)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd:socket文件描述符addr:成功与Sever建立连接的那个**客户端**的地址结构;传出参数,返回链接客户端地址信息(IP地址+端口号)addrlen:传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小 socklen_t clit_addr_len=sizeof(addr); 入: 传入addr的大小; 出: 客户端addr的实际大小;返回值: 成功: 返回能与客户端进行通信的socket对应的文件描述符; 失败: 返回-1并设置errno;//我们的服务器程序结构是这样的 while (1) {cliaddr_len = sizeof(cliaddr);connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);n = read(connfd, buf, MAXLINE);......close(connfd); }
connect函数(使用现有的socket与服务器建立连接)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockdf:socket文件描述符struct sockaddr_in srv_addr; // 服务器地址结构srv_addr.sin_family = AF_INET;srv_addr.sin_port = 9527 跟服务器bind时设定的 port 完全一致。inet_pton(AF_INET, "服务器的IP地址",&srv_adrr.sin_addr.s_addr);addr:传入参数,指定服务器端地址信息,含IP地址和端口号addrlen:传入参数,服务器地址结构的长度sizeof(addr)大小返回值: 成功返回0; 失败返回-1并设置errno;如果不使用`bind()`函数绑定客户端的地址结构, 会采用**"隐式绑定"**;
三:服务器模型和客户端模型的实现
Server服务器的实现
server:1. socket() 创建socket2. bind() 绑定服务器地址结构3. listen() 设置监听上限4. accept() 阻塞监听客户端连接5. read(fd) 读socket获取客户端数据6. 小--大写 toupper()7. write(fd)8. close();
代码逻辑
#include <stdio.h> #include <ctype.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <pthread.h>#define SERV_PORT 9527 //端口号int main(int argc, char *argv[]){int link_fd=0; //建立连接的socket文件描述符int connect_fd=0 //用于通信的文件描述符int ret=0; //用于检查是否出错char buf[BUFSIZ]; //缓冲区char client_IP[1024] //存入客户端IP字符串int num=0; //读出的字节数/*服务器端地址结构*/struct sockaddr_in serv_addr; // 定义服务器地址结构 和 客户端地址结构serv_addr.sin_family=AF_INET; // IPv4serv_addr.sin_port=htons(SERV_PORT); // 转为网络字节序的 端口号serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); // 获取本机任意有效IP/*成功与服务器建立连接的客户端地址结构*/struct sockaddr_in clint_addr;socklen_t clint_addr_len=sizeof(clint_addr); // 获取客户端地址结构大小/*1.socket函数:创建用于建立连接的socket,返回的文件描述符存入link_fd*///IPv4,按照顺序基于字节流的连接,指定代表协议link_fd=socket(AF_INET,SOCK_STREAM,0); if(link_fd==-1)sys_err("socket error");/*2.bind函数:绑定服务器端的socket绑定地址结构(IP+port)*///socket文件描述符link_fd,IP地址加端口号ret=bind(link_fd,(const struct sockaddr*)&serv_addr,sizeof(serv_addr));if(ret==-1)sys_err("bind error");/*3.listen函数:设定监听(连接)上线*/ret=listen(link_fd,128); if(ret==-1)sys_err("listen error");/*4.accept函数:阻塞等待客户端建立连接*///文件描述符,与Sever建立连接的客户端的地址结构,返回真正接收到地址结构体的大小connect_fd=accept(link_fd,( struct sockaddr*)&clint_addr,&clint_addr_len); if(connect_fd==-1)sys_err("accept error");/*建立连接后打印客户端的IP和端口号 获取客户端地址结构*/printf("client IP:%s,client port:%d", //`client_IP`是前面定义的客户端IP字符串的缓冲区, 大小为1024 inet_ntop(AF_INET,&clint_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)), //网络字节序 ---> 本地字节序ntohs(clint_addr.sin_port) //根据accept传出参数,获取客户端 ip 和 port); /*业务逻辑*/while(1){//5. read(fd) 读socket获取客户端数据num=read(connect_fd,buf,sizeof(buf)); // 读客户端数据write(STDOUT_FILENO,buf,num); // 写到屏幕查看//6. 小--大写 toupper()for(i=0;i<num;i++) // 小写 -- 大写buf[i]=toupper(buf[i]);//7. write(fd)write(connect_fd,buf,num); // 将大写,写回给客户端sleep(1);}//8. close()close(connect_fd);close(link_fd);return 0; }测试命令
`nc 127.0.0.1 9527` //脑残命令: 向这个服务发送信息并打印回执
Client客户端的实现
client:1. socket() 创建socket2. connect(); 与服务器建立连接3. write() 写数据到 socket4. read() 读转换后的数据5. 显示读取结果6. close()
代码逻辑
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <pthread.h>#define SERV_PORT 9527/*错误处理函数*/ void sys_err(const char* str){perror(str);exit(1); }int main(int argc, char *argv[])){int client_fd=0;int ret=0;int num=0;int cnt=10;char buf[BUFSIZ];//connect的参数2填入服务器的文件描述符!struct sockaddr_in serv_addr;serv_addr.sin_family=AF_INET;serv_addr.sin_port=htons(SERV_PORT);// 本地字节序(string IP) ---> 网络字节序inet_pton(AF_INET,"127.0.0.1",(void*)&serv_addr.sin_addr.s_addr);/*1. 创建socket():客户端直接创建用于连接的套接字即可*/client_fd=socket(AF_INET,SOCK_STREAM,0);if(client_fd==-1)sys_err("socket error");/*2. connect():将客户端套接字与服务器地址结构连接起来*/ret=connect(client_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));if(ret!=0)sys_err("connect error");//业务逻辑while(--cnt){//3. write() 写数据到 socketwrite(client_fd,"fuckyou\n",8);//4. read() 读转换后的数据。num=read(client_fd,buf,sizeof(buf));//5. 显示读取结果write(STDOUT_FILENO,buf,num);sleep(1);}//6. close()close(client_fd);return 0; }
相关文章:
Linux网络编程:Socket套接字编程(Server服务器 Client客户端)
文章目录: 一:定义和流程分析 1.定义 2.流程分析 3.网络字节序 二:相关函数 IP地址转换函数inet_pton inet_ntop(本地字节序 网络字节序) socket函数(创建一个套接字) bind函数(给socket绑定一个服务器地址结…...
Mac OS下应用Python+Selenium实现web自动化测试
在Mac环境下应用PythonSelenium实现web自动化测试 在这个过程中要注意两点: 1.在终端联网执行命令“sudo pip install –U selenium”如果失败了的话,可以尝试用命令“sudo easy_install selenium”来安装selenium; 2.安装好PyCharm后新建project&…...
每天一道leetcode:934. 最短的桥(图论中等广度优先遍历)
今日份题目: 给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。 岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。 你可以将任意数量的 0 变为 1 &#…...
【学习日记】【FreeRTOS】FreeRTOS 移植到 STM32F103C8
前言 本文基于野火 FreeRTOS 教程,内容是关于 FreeRTOS 官方代码的移植的注意事项,并将野火例程中 STM32F103RC 代码移植到 STM32F103C8。 一、FreeRTOS V9.0.0 源码的获取 两个下载链接: 官 网 代码托管 二、源码文件夹内容简介 Source…...
Qt 屏幕偶发性失灵
项目场景: 基于NXP i.mx7的Qt应用层项目开发,通过goodix使用触摸屏,走i2c协议。 问题描述 触摸屏使用过程中意外卡死,现场分为多种: i2c总线传输错误,直观表现为触摸屏无效,任何与触摸屏挂接在同一总线上的i2c设备,均受到干扰,并且在传输过程中内核报错以下代码: G…...
如何在pycharm中指定GPU
如何在pycharm中指定GPU 作者:安静到无声 个人主页 目录 如何在pycharm中指定GPU打开编辑配置点击环境变量添加GPU配置信息推荐专栏在Pycharm运行程序的时候,有时候需要指定GPU,我们可以采用以下方式进行设置: 打开编辑配置 点击环境变量 添加GPU配置信息 添加名称:CU…...
C#判断字符串中有没有字母,正则表达式、IsLetter
要判断字符串中是否包含字母,可以使用正则表达式或者循环遍历字符串的方式。 方法一:使用正则表达式 using System.Text.RegularExpressions;string input "Hello123"; bool containsLetter Regex.IsMatch(input, "[a-zA-Z]");上…...
Jtti:Ubuntu怎么限制指定端口和IP访问
在 Ubuntu 系统中,可以使用防火墙规则来限制特定的端口和IP访问。常用的防火墙管理工具是 iptables,以下是使用 iptables 来限制指定端口和IP访问的步骤: 安装 iptables: 如果系统中没有安装 iptables,可以使用以下命…...
机器学习/深度学习需要掌握的linux基础命令
很多深度学习/机器学习/数据分析等领域(或者说大多数在Python环境下进行操作的领域)的初学者入门时是在Windows上进行学习,也得益于如Anaconda等工具把环境管理做的如此友善 但如果想在该领域继续深耕,一定会与Linux操作系统打交…...
C++11 std::async推荐使用 std::launch::async 模式
async真假多线程 std::launch::async真多线程 std::launch::async | std::launch::deferred可能多线程 std::launch::deferred假多线程 枚举变量说明 枚举定义 enum class launch {async 1, // 0b1deferred 2, // 0b10any async | def…...
没有使用springboot 单独使用spring-boot-starter-logging
如果您不使用Spring Boot框架,但想单独使用Spring Boot Starter Logging,您可以按照以下步骤进行: 1. 添加Maven依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boo…...
创建Azure资源锁
锁的介绍 在Azure中,资源锁是一种用于保护订阅、资源组或者单个资源的机制。它可以防止对受锁定的资源进行删除或修改操作,帮助确保资源的连续可用性和安全性。 Azure中的资源锁可以分为两种类型: 删除锁(CanNotDelete…...
卷积神经网络教程 (CNN) – 使用 TensorFlow 在 Python 中开发图像分类器
在这篇博客中,让我们讨论什么是卷积神经网络 (CNN) 以及 卷积神经网络背后的架构——旨在解决 图像识别系统和分类问题。 卷积神经网络在图像和视频识别、推荐系统和自然语言处理方面有着广泛的应用。 目录 计算机如何读取图像? 为什么不是全连接网络?...
MyBatis XML映射处理CLOB和BLOB类型
Mybatis的MapperXML映射文件应该处理数据库字段类型为CLOB和BLOB类型的数据呢?首先我们先看下CLOB和BLOB这两种数据类型的介绍。 介绍 使用Mybatis时涉及到两种特殊类型的处理,分别是Blob(Binary Large Object)和Clob࿰…...
FPGA_学习_14_第一个自写模块的感悟和ila在线调试教程与技巧(寻找APD的击穿偏压)
前一篇博客我们提到了,如果要使用算法找到Vbr,通过寻找APD采集信号的噪声方差的剧变点去寻找Vbr是一个不错的方式。此功能的第一步是在FPGA中实现方差的计算,这个我们已经在上一篇博客中实现了。 继上一篇博客之后,感觉过了很久了…...
【2023新教程】树莓派定时自动拍照并上传腾讯云对象存储COS
1 换源 仅适用于Release date: May 3rd 2023、Debian version: 11 (bullseye)这个树莓派OS版本,其他版本不保证有效。 首先使用如下命令,查看自己树莓派的架构。 uname -a结果如下: 如果红圈处显示为aarch64,使用命令sudo na…...
校企合作谋发展 合作共赢谱新篇|云畅科技与湖南民族职业学院签订校企合作协议
产业是经济发展的重要引擎,人才是产业发展的重要资源。为积极探索软件人才培育新路径,共商政产学研协同新机制,8月8日,云畅科技与湖南省民族职业学院教育技术学院软件技术专业签订校企合作协议。 会上,学院副校长王志平…...
vue技术学习
vue快速入门 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>vue快速入门</title> </head> <body> <!--老师解读 1. div元素不是必须的,也可以是其它元素࿰…...
基于空间的图卷积神经网络:GNN
目录 欧氏空间中神经网络发挥巨大最作用,DNA,知识图谱三维或者多维空间不行 邻接矩阵实现图结构的矩阵化表示:造梦师 局和操作实现层内消息传递:带线的连接机传递消息 GCN通过邻域聚合实现特征提取 SVM支持向量机 编辑 硬分…...
.net core发布到IIS上出现 HTTP 错误 500.19
1.检查.net core 环境运行环境是否安装完成,类似如下环境 2.IIS是否安装全 本次原因就是IIS未安装全导致的 按照网上说的手动重启iis(iisreset)也不行...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...

