简明linux系统编程--互斥锁--TCP--UDP初识

目录

1.互斥锁

2.信号

2.1介绍

2.2信号的内核机制

3.linux网络编程概述

3.1一览七层协议

3.2一览数据传输过程

 3.3四层网络模型

3.4服务端和客户端的数据交互

4.TCP服务端编程

5.TCP客户端编程

6.UDP服务端编程

7.UDP客户端编程


1.互斥锁

互斥锁也是和信号量一样,用于进行任务之间的通信

我们的这个互斥锁,分为上锁和解锁,我们的某一个进程占用这个资源的时候,就会把这个共享区域上锁,表示这个空间资源已经被使用,其他的想要使用这个资源的进程就会被挂起,直到我们的这个正在使用资源的进程使用完毕,其他的被挂起的进程才可以使用这个资源,这个资源就会被从原来的上锁状态到现在的解锁状态,被其他的进程使用;

实际上这个互斥锁主要是是被线程使用,互斥锁不可能会同时被两个线程拥有,我们把这个称之为排他性;

已经处于加锁的状态的互斥锁,被其他的线程访问,这个线程就会被加锁,只有这个互斥锁解锁的时候,其他的线程才可以使用;

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>//两个线程函数的声明
void *thread1_function(void *arg);
void *thread2_function(void *arg);pthread_mutex_t mutex;//创建互斥锁//主函数进行互斥锁的创建和初始化,以及线程的创建
int main(void)
{pthread_t pthread1, pthread2;int ret;//初始化互斥锁//第二个就是默认的配置选项pthread_mutex_init(&mutex, NULL);ret = pthread_create(&pthread1, NULL, thread1_function, NULL);if(ret != 0){perror("pthread_create");exit(1);}ret = pthread_create(&pthread2, NULL, thread2_function, NULL);if(ret != 0){perror("pthread_create");exit(1);}//线程的连接,第一个参数就是连接线程的线程号pthread_join(pthread1, NULL);pthread_join(pthread2, NULL);printf("The thread is over, process is over too.\n");return 0;
}//线程1的操作:上锁
void *thread1_function(void *arg)
{int i;while(1){//这个函数就是对于这个进行初始化的互斥锁进行上锁pthread_mutex_lock(&mutex);for(i = 0; i < 10; i++){printf("Hello world\n");sleep(1);}//循环休眠之后进行解锁的操作pthread_mutex_unlock(&mutex);sleep(1);}return NULL;
}//线程2的操作:先是阻塞挂起,然后加锁(线程1已经占用完成)
void *thread2_function(void *arg)
{int i;//确保线程1先运行,开始的时候让这个线程1先运行sleep(1);while(1){//尝试加锁,但是会处于阻塞状态pthread_mutex_lock(&mutex);for(i = 0; i < 10; i++){//这个就是线程1使用完之后,才会打印这个good morningprintf("Good moring\n");sleep(1);}pthread_mutex_unlock(&mutex);sleep(1);}return NULL;
}

2.信号

2.1介绍

数据传输方式:管道,共享内存,消息队列;

信号主要用途:传递控制命令,主要是进程和应用程序之间,或者是应用程序之间;

2.2信号的内核机制

其实这个信号我们经常使用,只不过这次是说出了他的真正的名字,我们之前使用的这个ctrl+c就是退出这个程序,ctrl+z就是强制退出,这些都是我们的信号;

我们的这个信号有的是我们自己可以控制的,有的就是属于内核层面上面的,是固定的,即使我们进行自定义,他也不会按照我们的定义去修改;

下面的这个就是我们传递命令行参数,通过这个kill函数控制第二个程序里面运行的线程,我们的这个kill函数里面的传递的这个内容就是相当于信号,控制这个function里面的线程的执行;

int main(int argc, char *argv[])
{kill(atoi(argv[1]), SIGQUIT);return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>void function(int signo);int main(void)
{int i = 0;printf("pid = %d\n", getpid());signal(SIGINT, function);signal(SIGKILL, function);while(1){printf("Count to %d\n", ++i);sleep(1);}return 0;
}void function(int signo)
{//把ctrl+c的这个处理机制重写了if(signo == SIGINT){printf("You have just triggered a ctrl+c operation.\n");exit(1);}else if(signo == SIGQUIT)printf("Trig a SIGQUIT signal.\n");
}

有些时候,我们传递这个信号的时候,这个控制程序并不会按照我们的这个设计输出打印结果,例如这个,我们虽然指定了这个信号的打印结果,但是如果这个信号是内核层面的,我们就无法进行修改,这个时候打印的时候就不会按照我们的设计进行打印,而是按照系统的内核设计;

3.linux网络编程概述

3.1一览七层协议

3.2一览数据传输过程

发送就是封装的过程,接收数据就是解封的过程,类似于我们的这个快递的传输过程,发送这个快递的时候需要不断的进行打包,当我们取到这个快递的时候就需要不断地进行包装的拆解;

这个里面的主机A就相当于这个快递发送端,这个主机B就相当于这个我们对于这个数据进行拆解的过程;

 3.3四层网络模型

下面的这个四层模型就是上面的这个模型简化之后得到的:

TCP协议面向连接,建立连接之后,这个内容才会被发送,稳定传输数据;

UDP不是面向连接的,不稳定,不可靠,可能发送端和接收端没有建立连接,这个数据就会被发送出去了;

TCP因为确认连接的过程繁琐,传输的效率很低,UDP的传输效率相对较高,我们需要根据我们的具体需求进行选择;

当我们发送的数据比较大的时候,就是使用的UDP协议,例如看视频,顶多出现卡顿现象;

如果我们需要确保接收端收到数据,我们需要使用更加安全的TCP;

3.4服务端和客户端的数据交互

4.TCP服务端编程

#include <stdio.h>//下面的两个头文件是使用socket函数需要包含的
#include <sys/types.h>
#include <sys/socket.h>//htons函数需要包含下面的这个头文件
#include <arpa/inet.h>#include <netinet/in.h>
#include <unistd.h>#define PORT_ID	8800
#define SIZE	100int main(void)
{int sockfd, client_sockfd;//这个结构体的struct sockaddr_in my_addr, client_addr;int addr_len;char welcome[SIZE] = "Welcome to connect to the sever!";//1.socket()创建用于通信的节点,返回节点的描述符-----------------------------------------------------//第一个参数配置通信域//AF_INET表示我们使用的是IPV4标准//SOCK_STREAM表示的就是TCP协议的套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);//2.bind()---------------------------------------------------------------------------------------my_addr.sin_family = AF_INET;//设置端口号,应用层上面的,这个时候,//因为计算机和网络的大小端可能不统一,//我们使用这个htons函数把主机和网络的字节序进行转换统一(全部转换为大端模式)my_addr.sin_port = htons(PORT_ID);//INADDR_ANY参数表示的是监视计算机上面的所有网卡的数据my_addr.sin_addr.s_addr = INADDR_ANY;//把一个名字绑定到我们的套接字上面bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));//3.listen():监听套接字的连接---------------------------------------------------------------------//sockfd表示需要监听的套接字描述符listen(sockfd, 10);addr_len = sizeof(struct sockaddr);while(1){printf("Server is waiting for client to connect:\n");//4.accept():等待客户端的请求----------------------------------------------------------------------------------//第二个参数:访问过来的客户端的地址//这个就是输出型参数(运行完之后客户端的地址就被放到这个位置,不需要我们手动填充)//accept返回值就是新的套接字描述符,新的客户端描述符,客户端有请求,就会返回新的套接字描述符client_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &addr_len);//inet_ntoa函数作用就是把我们的internet主机地址从二进制转换为点分的10进制,例如这个192.168.等等之类的printf("Client IP address = %s\n", inet_ntoa(client_addr.sin_addr));//5.send()服务器发送消息到客户端--------------------------------------------------------------------------------//第二个参数就是发送的内容char welcome[SIZE] = "Welcome to connect to the sever!";send(client_sockfd, welcome, SIZE, 0);printf("Disconnect the client request.\n");//6.close()---关闭客户端的连接---------------------------------------------------------------------------------close(client_sockfd);}close(sockfd);return 0;
}

5.TCP客户端编程

#define PORT_ID	8800
#define SIZE	100//./client IP  : ./client 192.168.0.10
int main(int argc, char *argv[])
{int sockfd;//这个结构体里面的是服务器端的这个地址struct sockaddr_in server_addr;char buf[SIZE];//当我们输入的参数后面没有这个IP地址的时候,我们需要给出这个提示信息,提示用户给出来IP地址//agrc表示的就是参数的个数if(argc < 2){printf("Usage: ./client [server IP address]\n");exit(1);}//1.socket()sockfd = socket(AF_INET, SOCK_STREAM, 0);//2.connect()server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT_ID);//argv[1]这个表示的就是命令行参数里面和IP地址相关的这个参数server_addr.sin_addr.s_addr = inet_addr(argv[1]);connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));//recv函数表示服务器端对于客户端发来的数据的接受,buf这个表示接受的信息内容放到buf里面去recv(sockfd, buf, SIZE, 0);printf("Client receive from server: %s\n", buf);close(sockfd);return 0;
}

6.UDP服务端编程

和上面的这个TCP想比较,这个UDP就简单了很多:

UDP没有accept函数获得客户端的信息,我们无法知道谁发送给我们的信息;

我们想要获得这个谁发送的,我们使用这个recvfrom知道谁发送到我们客户端的;

#define PORT_ID	8800
#define SIZE	100int main(void)
{int sockfd;struct sockaddr_in my_addr, client_addr;int addr_len;char buf[SIZE];//1.socket()sockfd = socket(AF_INET, SOCK_DGRAM, 0);//2.bind()my_addr.sin_family = AF_INET;my_addr.sin_port = htons(PORT_ID);my_addr.sin_addr.s_addr = INADDR_ANY;bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));addr_len = sizeof(struct sockaddr);while(1){printf("Server is waiting for client to connect:\n");//4.recvfrom()函数可以让我们知道这个接收到的数据的来源recvfrom(sockfd, buf, SIZE, 0, (struct sockaddr *)&client_addr, &addr_len);printf("Server receive from client: %s\n", buf);}close(sockfd);return 0;
}

7.UDP客户端编程

#define PORT_ID	8800
#define SIZE	100//./client IP  : ./client 192.168.0.10
int main(int argc, char *argv[])
{int sockfd;struct sockaddr_in server_addr;char buf[SIZE];int i;if(argc < 2){printf("Usage: ./client [server IP address]\n");exit(1);}//1.socket()sockfd = socket(AF_INET, SOCK_DGRAM, 0);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT_ID);server_addr.sin_addr.s_addr = inet_addr(argv[1]);for(i = 0; i < 10; i++){sprintf(buf, "%d\n", i);sendto(sockfd, buf, SIZE, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));printf("Client sends to server %s: %s\n", argv[1], buf);sleep(1);}close(sockfd);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】——优先级队列和容器适配器

文章目录 优先级队列容器适配器 优先级队列 优先级队列是一种特殊的队列&#xff0c;他的元素出队列顺序并不按照先进先出原则&#xff0c;而是根据元素的优先级来。优先级高的先出&#xff0c;优先级低的后出。(类似于堆) 优先级队列常用成员函数&#xff1a; empty()&#x…

6.C++程序中的基本数据类型

数据类型是指在C中用于声明不同类型变量或函数的一个系统或抽象或者是一个分类&#xff0c;它决定了变量存储占用的内存空间以及解析存储的位模式。其实数据类型可以理解为固定内存大小的别名&#xff0c;是创建变量的模具&#xff0c;具体使用哪种模具&#xff08;包括自定义&…

ai写作软件排行榜前十名,5个软件帮助你快速使用ai写作

ai写作软件排行榜前十名&#xff0c;5个软件帮助你快速使用ai写作 AI写作软件已经成为许多人工作和创作中的重要工具&#xff0c;尤其是在快速生成内容、提高写作效率以及优化文本方面。以下是五款优秀的AI写作软件&#xff0c;它们能够帮助你轻松完成各种写作任务&#xff0c…

芯片级配件产品研发的小众企业生存之路

在半导体行业中&#xff0c;芯片级配件产品的研发一直是一个充满挑战的领域&#xff0c;尤其是对于小众企业而言&#xff0c;如何在技术壁垒高、资金需求大的市场中生存并发展&#xff0c;成为了业界普遍关注的问题。芯片级配件产品涉及到晶圆制造、封装、测试等多个复杂工艺环…

计算机人工智能前沿进展-大语言模型方向-2024-09-20

计算机人工智能前沿进展-大语言模型方向-2024-09-20 1. Multimodal Fusion with LLMs for Engagement Prediction in Natural Conversation Authors: Cheng Charles Ma, Kevin Hyekang Joo, Alexandria K. Vail, Sunreeta Bhattacharya, Alvaro Fern’andez Garc’ia, Kailan…

码头童话,“丈量”行业数智化转型

作者 | 曾响铃 文 | 响铃说 一箱车厘子从地球正对的另一边远渡重洋来到中国&#xff0c;而一旦到达&#xff0c;5个小时内它就能变成北京、天津、河北、河南等区域老百姓果盘里的美味。 这一幕&#xff0c;来自央视联合华为制作发布的《新智中国说-谈智一会间》第一期“码头…

win10下使用docker、k8s部署java应用

在上一篇文章 Windows10上Docker和Kubernetes的安装 中&#xff0c;已经介绍了在 Windows10上安装Docker和Kubernetes &#xff0c;有了这个环境基础之后&#xff0c;就可以用来部署服务了 在项目目录下新建Dockfile文件&#xff0c;内容如下&#xff08;请根据实际情况调整&am…

鸿蒙开发之ArkUI 界面篇 十五 交叉轴对其方式

鸿蒙界面有两个容器一个是Colum、一个是Row&#xff0c;Colum主轴是垂直方向&#xff0c;交叉轴是水平方向&#xff0c;Row的主轴是水平方向&#xff0c;交叉轴是垂直方向&#xff0c;对应方向调整子控件的话&#xff0c;justifyContent调整的是主轴方向的子控件距离&#xff0…

Java发送Outlook邮件:从设置到发送攻略!

Java发送Outlook邮件详细步骤&#xff01;如何使用Java发邮件&#xff1f; Java作为一种广泛使用的编程语言&#xff0c;提供了强大的功能来实现自动化邮件发送。AokSend将详细介绍如何使用Java发送Outlook邮件&#xff0c;从基本的设置到最终的发送过程。 Java发送Outlook邮…

美元降息,对普通人有哪些影响?

美元降息&#xff0c;对普通人有哪些影响&#xff1f; 美元降息了。很多朋友都说我又不炒股&#xff0c;我手里又没有美金&#xff0c;美元跟我有啥关系啊&#xff1f;那我们就来聊聊美元降息&#xff0c;对我们国内经济到底有哪些影响&#xff1f;你再来看看跟你有没有关系&a…

短视频矩阵系统开发|技术源代码部署

产品功能亮点&#xff1a; 1. 支持多账号多平台一键 授权管理 2.支持矩阵视频批量剪辑&#xff0c;批量发布 3. 多平台关键词布局&#xff0c;提升企业及产品曝光 4. 评论区关键词自动回复&#xff0c;意向线索智能挖掘 5. 多账号投放数据统计&#xff0c;省时省力 6. 留资…

Jmeter 线程组解析

1.seUp线程组 一种特殊的 threadGroup &#xff0c;可用于执行预测试操作&#xff1b;它的行为完全像一个正常的线程组元件&#xff0c;不同的是执行顺序。 它会在普通线程组执行之前被触发。 应用场景&#xff1a; 测试数据库操作功能时&#xff0c;用于执行打开数据库连接的…

jetcache-阿里多级缓存框架神器一定要掌握

文章目录 1. 简介2. springboot集成jetcache2.1 引入依赖2.2 配置文件2.3 高级API模式&#xff1a;通过CacheManager使用缓存&#xff0c;2.7 版本才可使用2.4 &#xff08;推荐&#xff09;AOP模式&#xff1a;通过Cached,CacheUpdate,CacheInvalidate注解 1. 简介 JetCache是…

Redis基本命令详解

1. 基本命令 命令不区分大小写&#xff0c;而key是区分大小写的 # select 数据库间的切换 数据库共计16个 127.0.0.1:6379> select 1# dbsize 返回当前数据库的 key 的数量 127.0.0.1:6379[1]> dbsize# keys * 查看数据库所有的key 127.0.0.1:6379[1]> keys *# fl…

SpringBoot+Vue+MySQL驾校预约管理系统

目录 前言 功能设计 系统实现 获取源码 博主主页&#xff1a;百成Java 往期系列&#xff1a;Spring Boot、SSM、JavaWeb、python、小程序 前言 随着社会的进步&#xff0c;各行各业都在充分利用信息化时代的优势。由于计算机技术的广泛应用和普及&#xff0c;各种信息系统…

极越联手百度这你受得了吗!SU7还能稳坐“7字辈”头把交椅?

文/王俣祺 导语&#xff1a;自从今年上半年小米SU7标榜为“年轻人的第一台纯电轿车”&#xff0c;各家车企全都坐不住了。尤其是与小米“颇有渊源”的吉利&#xff0c;从极氪再到领克&#xff0c;目标已经可以说是路人皆知了。现在极越07也来了&#xff0c;可以看出吉利也是下了…

在Windows环境下设置SSH克隆GitHub仓库

在Windows环境下设置SSH克隆GitHub仓库的步骤如下&#xff1a; 1. 生成SSH密钥 打开 Git Bash&#xff08;如果你已经安装了Git&#xff09;。输入以下命令生成SSH密钥&#xff1a;ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 按 Enter 键接受默认文件名…

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【内核通信机制】下

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 子系统开发内核 轻量系统内核&#xff08;LiteOS-M&#xff09; 轻量系统内核&#…

d3dcompiler47dll丢失怎么解决,详细介绍6种解决方案

在电脑使用过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是系统提示某个文件缺失。其中&#xff0c;d3dcompiler_47.dll是许多用户经常遇到的问题之一。这个文件是DirectX组件的一部分&#xff0c;如果缺失&#xff0c;可能会导致游戏或应用程序无法正常运行…

Python学习——【3.1】函数

文章目录 【3.1】函数一、函数的定义二、函数的参数三、函数的返回值&#xff08;一&#xff09;函数返回值的定义&#xff08;二&#xff09;None类型 四、函数的说明文档五、函数的嵌套调用六、函数中变量的作用域&#xff08;一&#xff09;局部变量&#xff08;二&#xff…