网络编程打开的第一节预备课-----关于socket

一、引言

传统的进程间通信借助内核提供的 IPC 机制进行, 但是只能限于本机通信, 若
要跨机通信, 就必须使用网络通信,比如之前在操作系统学习到的pipe通信,这是一个本机通信,是最基本的IPC机制进行的。

socket网络通信和pipe通信的区别在于:

1. socket可以建立一个socket pair,使用文件描述符操作两个缓冲区,而pipe是两个文件描述符操作一个内核缓冲区。

2. 在网络传输中,需要考虑大端和小端的问题,而pipe通信则不需要。

3. socket通信适用于跨机通信,而pipe通信只能限于本机通信。

 

二、socket 编程预备知识

网络字节序:
      大端和小端的概念
           大端: 低位地址存放高位数据, 高位地址存放低位数据
           小端: 低位地址存放低位数据, 高位地址存放高位数据

大端和小端只是对数据类型长度是两个及以上的, 如 int short, 对于单字节
没限制, 在网络中经常需要考虑大端和小端的是 IP 和端口.

比如:0x12345678 如何存放?

将十六进制数 0x12345678 拆分成四个字节,分别为 0x12、0x34、0x56、0x78。

按照大端:0x12345678。

按照小端:0x78563412

如何测试本机是否是大端还是小端

#include <stdio.h>int main() {union {int i;char c[4];} endianTest;endianTest.i = 1;if (endianTest.c[0] == 1) {printf("本机是小端模式\n");} else {printf("本机是大端模式\n");}return 0;
}

网络传输用的是大端法, 如果机器用的是小端法, 则需要进行大小端的转换.

下面 4 个函数就是进行大小端转换的函数:

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
函数名的 h 表示主机 host, n 表示网络 network, s 表示 short, l 表示 long
 

IP地址转换函数:

 (1)int inet_pton(int af, const char *src, void *dst);

函数说明: 将字符串形式的点分十进制IP转换为大端模式的网络IP(整形4字节数)

参数说明:

        af: AF_INET(指定要使用的地址族类型)

        src: 字符串形式的点分十进制的IP地址

        dst: 存放转换后的变量的地址

例如: inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);

手工也可以计算: 如192.168.232.145, 先将4个正数分别转换为16进制数,

192--->0xC0  168--->0xA8   232--->0xE8   145--->0x91

最后按照大端字节序存放: 0x91E8A8C0, 这个就是4字节的整形值.

(2)const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

函数说明: 网络IP转换为字符串形式的点分十进制的IP

参数说明:

        af: AF_INET

        src: 网络的整形的IP地址

        dst: 转换后的IP地址,一般为字符串数组

        size: dst的长度

返回值:

        成功--返回指向dst的指针

        失败--返回NULL, 并设置errno

例如: IP地址为010aa8c0, 转换为点分十进制的格式:

01---->1    0a---->10   a8---->168   c0---->192

由于从网络中的IP地址是高端模式, 所以转换为点分十进制后应该为: 192.168.10.1

通过man 7 ip可以查看相关说明:

struct sockaddr结构说明:

   struct sockaddr {

        sa_family_t sa_family;

        char     sa_data[14];

   }

struct sockaddr_in结构:

struct sockaddr_in {

         sa_family_t    sin_family; /* address family: AF_INET */

         in_port_t      sin_port;   /* port in network byte order */

         struct in_addr sin_addr;   /* internet address */

   };

   /* Internet address. */

   struct in_addr {

         uint32_t  s_addr;     /* address in network byte order */

   };  //网络字节序IP--大端模式

三、主要socket函数API介绍

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

函数描述: 创建socket

参数说明:

domain: 协议版本

        AF_INET IPV4

        AF_INET6 IPV6

        AF_UNIX AF_LOCAL本地套接字使用

type:协议类型

        SOCK_STREAM 流式, 默认使用的协议是TCP协议

        SOCK_DGRAM  报式, 默认使用的是UDP协议

protocal:

        一般填0, 表示使用对应类型的默认协议.

返回值:

        成功: 返回一个大于0的文件描述符

        失败: 返回-1, 并设置errno

当调用socket函数以后, 返回一个文件描述符, 内核会提供与该文件描述符相对应的读和写缓冲区, 同时还有两个队列, 分别是请求连接队列和已连接队列.

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

函数描述: 将socket文件描述符和IP,PORT绑定

参数说明:

        socket: 调用socket函数返回的文件描述符

        addr: 本地服务器的IP地址和PORT,

        struct sockaddr_in serv;

        serv.sin_family = AF_INET;

        serv.sin_port = htons(8888);

        //serv.sin_addr.s_addr = htonl(INADDR_ANY);

        //INADDR_ANY: 表示使用本机任意有效的可用IP

        inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);

addrlen: addr变量的占用的内存大小

返回值:

        成功: 返回0

        失败: 返回-1, 并设置errno

(3)int listen(int sockfd, int backlog);

函数描述: 将套接字由主动态变为被动态

参数说明:

        sockfd: 调用socket函数返回的文件描述符

        backlog: 同时请求连接的最大个数(还未建立连接)

返回值:

        成功: 返回0

        失败: 返回-1, 并设置errno

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

函数说明:获得一个连接, 若当前没有连接则会阻塞等待.

函数参数:

        sockfd: 调用socket函数返回的文件描述符

        addr: 传出参数, 保存客户端的地址信息

        addrlen: 传入传出参数,  addr变量所占内存空间大小

返回值:

        成功: 返回一个新的文件描述符,用于和客户端通信

        失败: 返回-1, 并设置errno值.

accept函数是一个阻塞函数, 若没有新的连接请求, 则一直阻塞.

从已连接队列中获取一个新的连接, 并获得一个新的文件描述符, 该文件描述符用于和客户端通信.  (内核会负责将请求队列中的连接拿到已连接队列中)

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

函数说明: 连接服务器

函数参数:

        sockfd: 调用socket函数返回的文件描述符

        addr: 服务端的地址信息

        addrlen: addr变量的内存大小

返回值:

        成功: 返回0

        失败: 返回-1, 并设置errno值

接下来就可以使用write和read函数进行读写操作了.

除了使用read/write函数以外, 还可以使用recv和send函数

读取数据和发送数据:

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, const void *buf, size_t count);

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

对应recv和send这两个函数flags直接填0就可以了.

注意: 如果写缓冲区已满, write也会阻塞, read读操作的时候, 若读缓冲区没有数据会引起阻塞.

使用socket的API函数编写服务端和客户端程序的步骤图示:

测试过程中可以使用netstat命令查看监听状态和连接状态

netstat命令:

        a表示显示所有,

        n表示显示的时候以数字的方式来显示

        p表示显示进程信息(进程名和进程PID)        

常用的netstat -anp | grep 8888  可以查看端口为8888的网络连接状态

四、服务端和客户端代码

客户端代码:

//客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>int main()
{//创建socket---用于和服务端进行通信int cfd = socket(AF_INET, SOCK_STREAM, 0);if(cfd<0){perror("socket error");return -1;}//连接服务端//int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);struct sockaddr_in serv;serv.sin_family = AF_INET;serv.sin_port = htons(8888);inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);printf("[%x]\n", serv.sin_addr.s_addr);int ret = connect(cfd, (struct sockaddr *)&serv, sizeof(serv));if(ret<0){perror("connect error");return -1;}   int n = 0;char buf[256];while(1){printf("请输入字符串:\n");//读标准输入数据memset(buf, 0x00, sizeof(buf));n = read(STDIN_FILENO, buf, sizeof(buf));//发送数据write(cfd, buf, n);//读服务端发来的数据memset(buf, 0x00, sizeof(buf));n = read(cfd, buf, sizeof(buf));if(n<=0){printf("read error or server closed, n==[%d]\n", n);break;}printf("转化为大写的符串为:%s\n",buf);}//关闭套接字cfdclose(cfd);return 0;
}

服务端代码:

//服务端程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>int main(){int lfd = socket(AF_INET,SOCK_STREAM,0);if(lfd < 0){perror("socket error");return -1;}struct sockaddr_in serv;bzero(&serv,sizeof(serv));serv.sin_family = AF_INET;serv.sin_port = htons(8888);serv.sin_addr.s_addr = htonl(INADDR_ANY);int ret = bind(lfd,(struct sockaddr *)&serv,sizeof(serv));if(ret<0){perror("bind error");   return -1;}listen(lfd,128);struct sockaddr_in client;socklen_t len =  sizeof(client);int cfd = accept(lfd,(struct sockaddr*)&client,&len);int i;int n;char buf[1024];while(1){//读数据memset(buf,0x00,sizeof(buf)); n = read(cfd,buf,sizeof(buf));if(n <= 0){printf("read error or client close n == [%d]\n",n);break;}printf("n == [%d],buf == [%s]\n",n,buf);for(i = 0;i < n;i ++){buf[i] = toupper(buf[i]);}write(cfd,buf,n);}close(lfd);close(cfd);}

按照上面代码,先启动服务端代码,再去启动客户端代码,根据客户端代码提示,完成客户端实现大小写字母转化

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AVL树性质和实现

AVL树 AVL是两名俄罗斯数学家的名字&#xff0c;以此纪念 与二叉搜索树的区别 AVL树在二叉搜索树的基础上增加了新的限制&#xff1a;需要时刻保证每个树中每个结点的左右子树高度之差的绝对值不超过1 因此&#xff0c;当向树中插入新结点后&#xff0c;即可降低树的高度&…

nn.embedding函数详解(pytorch)

提示&#xff1a;文章附有源码&#xff01;&#xff01;&#xff01; 文章目录 前言一、nn.embedding函数解释二、nn.embedding函数使用方法四、模型训练与预测的权重变化探讨 前言 最近发现prompt工程(如sam模型)&#xff0c;也有transform的detr模型等都使用了nn.Embedding函…

数据结构大体体系

逻辑结构 线性结构线性表一串珠子用线连起来&#xff0c;这就是典型的“线性存储结构”。每颗珠子之间的关系结构也很简单&#xff0c;包括头尾的话&#xff0c;它们最少有一个关系对象&#xff0c;而中间的珠子无论前后都只有一个关系对象&#xff0c;即 one-to-one栈队列字符…

Chatgpt人工智能对话源码系统分享 带完整搭建教程

ChatGPT的开发基于大规模预训练模型技术。预训练模型是一种在大量文本数据上进行训练的模型&#xff0c;可以学习到各种语言模式和知识。在ChatGPT中&#xff0c;预训练模型被用于学习如何生成文本&#xff0c;并且可以用于各种不同的任务&#xff0c;如对话生成、问答、摘要等…

时序预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost时间序列预测

时序预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于LSSVM-Adaboos…

全球10米土地覆盖产品(ESA)数据集2020和2021年

简介 全球10米土地覆盖产品(ESA)来源于欧空局&#xff0c;是基于哨兵一号、哨兵二号数据制作的2020年的10m分辨率的全球土地覆盖数据。土地利用数据一共分为11类&#xff0c;分别是:林地、灌木、草地、耕地、建筑、裸地/稀疏植被区、雪和冰、开阔水域、草本湿地、红树林、苔藓…

贰[2],QT异常处理

1&#xff0c;异常&#xff1a;QT编译警告 warning LNK4042: 对象被多次指定&#xff1b;已忽略多余的指定 处理办法&#xff0c;检查.pri文件&#xff0c;是否关联了多个相同的文件(头文件.h/源文件.cpp) 2&#xff0c;异常&#xff1a;C4819: 该文件包含不能在当前代码页(936…

云尘 命令执行系列

第一题 system <?php include "flag.php";if (isset($_POST[cmd])) {system($_POST[cmd]); }show_source(__FILE__);代码如上 system($_POST[cmd]); POST请求发送一个名为 cmd 的参数&#xff0c;然后将该参数的值传递给系统命令执行函数 system()&#xff0c…

C语言学习笔记之结构篇

C语言是一门结构化程序设计语言。在C语言看来&#xff0c;现实生活中的任何事情都可看作是三大结构或者三大结构的组合的抽象&#xff0c;即顺序&#xff0c;分支&#xff08;选择&#xff09;&#xff0c;循环。 所谓顺序就是一条路走到黑&#xff1b;生活中在很多事情上我们都…

Spring Boot项目中通过 Jasypt 对属性文件中的账号密码进行加密

下面是在Spring Boot项目中对属性文件中的账号密码进行加密的完整步骤&#xff0c;以MySQL的用户名为root&#xff0c;密码为123321为例&#xff1a; 步骤1&#xff1a;引入Jasypt依赖 在项目的pom.xml文件中&#xff0c;添加Jasypt依赖&#xff1a; <dependency><…

ClickHouse 学习之从高级到监控以及备份(二)

第 一 部分 高级篇 第 1 章 Explain 查看执行计划 在 clickhouse 20.6 版本之前要查看 SQL 语句的执行计划需要设置日志级别为 trace 才能可以看到&#xff0c;并且只能真正执行 sql&#xff0c;在执行日志里面查看。在 20.6 版本引入了原生的执行计划的语法。在 20.6.3 版本成…

ubuntu 20.04 server安装

ubuntu 20.04 server安装 ubuntu-20.04.6-live-server-amd64.iso 安装 安装ubuntu20.04 TLS系统后&#xff0c;开机卡在“A start job is running for wait for network to be Configured”等待连接两分多钟。 cd /etc/systemd/system/network-online.target.wants/在[Servi…

揭开堆叠式自动编码器的强大功能

一、介绍 在不断发展的人工智能和机器学习领域&#xff0c;深度学习技术因其处理复杂和高维数据的能力而广受欢迎。在各种深度学习模型中&#xff0c;堆叠式自动编码器是一种多功能且功能强大的工具&#xff0c;可用于特征学习、降维和数据表示。本文探讨了堆叠式自动编码器在深…

R语言实操记录——导出高清图片(矢量图)

R语言 R语言实操记录——导出高清图片&#xff08;矢量图&#xff09; 文章目录 R语言一、起因&#xff08;闲聊&#xff0c;可跳过&#xff09;二、如何在R中导出高清图片&#xff08;矢量图&#xff09;2.1、保存为EPS图片格式后转AI编辑2.2、保存为PDF格式&#xff08;推荐…

LabVIEW实现变风量VAV终端干预PID控制

LabVIEW实现变风量VAV终端干预PID控制 变风量&#xff08;VAV&#xff09;控制方法的研究一直是VAV空调研究的重点。单端PID控制在温差较大时&#xff0c;系统容易出现过冲。针对空调终端单端PID控制的不足&#xff0c;设计一种干预控制与PID控制耦合的控制方法。项目使用LabV…

关于Alibaba Cloud Toolkit 下载配置以及后端自动部署

idea中File-Settings-Plugins 搜索Alibaba Cloud Toolkit点击下载&#xff0c;下载完成重启 1、点击 Tools-Alibaba Cloud-Deploy to Host 部署到主机 2、配置服务器ip、jar包启动命令、服务器jar存放位置 3、设置服务器ip用户名密码&#xff0c;点击测试连接情况 4、配置脚本…

Flink SQL TopN语句详解

TopN 定义&#xff08;⽀持 Batch\Streaming&#xff09;&#xff1a; TopN 对应离线数仓的 row_number()&#xff0c;使⽤ row_number() 对某⼀个分组的数据进⾏排序。 应⽤场景&#xff1a; 根据 某个排序 条件&#xff0c;计算 某个分组 下的排⾏榜数据。 SQL 语法标准&am…

基于Java+SpringBoot+LayUI仓库管理系统

一.项目介绍 本项目是使用JavaSpringBoot开发&#xff0c;可以实现仓库的注册、登录&#xff0c;登录后可进入系统&#xff0c;进行客户管理、供应商管理、商品管理、商品退货查询管理、登录日志及退出等几大模块。系统界面采用传统的后台管理界面&#xff0c;界面简单、直观。…

【大数据】NiFi 中的处理器(一):GenerateTableFetch

NiFi 中的处理器&#xff08;一&#xff09;&#xff1a;GenerateTableFetch 1.简介2.应用场景3.示例3.1 案例一&#xff1a;无输入流文件&#xff0c;来源表含增量字段3.2 案例二&#xff1a;无输入流文件&#xff0c;不含增量字段3.3 案例三&#xff1a;无输入流文件&#xf…

Transformer的最简洁pytorch实现

目录 前言 1. 数据预处理 2. 模型参数 3. Positional Encoding 4. Pad Mask 5. Subsequence Mask 6. ScaledDotProductAttention 7. MultiHeadAttention 8. FeedForward Networks 9. Encoder Layer 10. Encoder 11. Decoder Layer 12. Decoder 13. Transformer 1…