【Linux】单机版QQ之管道中的命名管道(下)

简介: 【Linux】单机版QQ之管道中的命名管道(下)

同样我们要先创建一个缓冲区,然后直接循环写入消息,然后将写入的消息放到我们的缓冲区中,用一个指针接收客户输入的字符串,如果成功了这个指针保存的就是字符串的起始地址,我们在接收字符串的时候并不需要考虑\0,因为fgets这是C语言函数会自动加上\0的,断言一下空指针,然后将指针强转是为了防止出现在release版本变量被定义但是却没有使用的情况。buffer(len-1)是什么意思呢?这里其实是因为我们客户端输入字符串后会按一下回车,而回车也会被放入缓冲区中,这样的话在打印的时候服务端会多一行空白,所以我们把回车删掉就没有问题了。接下来我们让客户端输入quit的时候就退出程序,因为我们在服务端设置的是只要客户端退出服务端也就跟着退出了。然后我们向文件里写数据,把我们缓冲区的数据写到文件中,在这里同样不用考虑\0,因为只有C语言规定字符串后面必须加\0,而write是系统接口不会考虑\0的。做完这一步后我们断言一下函数返回值,不让返回值大于等于0的意思是如果是空串或者错误就不去写入了。然后同样强转一下刚刚的返回值n。最后我们将文件关闭即可,下面我们就试试可以运行吗:


运行的时候我们必须开两个窗口,当创建好两个可执行程序后,我们先运行服务端程序,这个时候程序会卡着不动,因为服务端要等待客户端打开同一个文件所以我们在运行客户端:

6d8d5d29d59b47e2b90e289c8c8bdd9f.png


这样我们就完成了命名管道的通信,这里还有一个问题就是当我们运行一次程序后就有了管道文件下一次运行程序会出现文件已经存在的报错,所以我们可以直接在服务端关闭文件后取消链接这个文件:

8e35e05f10204dd98ebc46684eb0f01d.png

这样的话我们每次运行程序就不用先将管道文件删除再运行了。


下面我们将这个命名管道改为用户每输入一个字符,服务端就相应的输出一个字符,大家可以理解为就像我们将手机投屏到电脑上手机上做什么操作电脑屏幕就是什么操作。


因为我们前面的实现每次需要输入回车服务端才会显示消息,现在我们需要不输入回车就写入内容的函数,这里我们用的getch函数,由于getch需要用到ncurses库,所以我们先安装这个库:


(按照ncurses库这个方法我们没有搞定,如果有搞定的小伙伴可以私信我哦~成功的方法在下面我用红字提醒出来了可直接找到后用系统方法)


fe7d77eb5389405cb04e0b197e76d6f2.png


如果大家是普通用户的话前面记得加上sudo提权。安装好后我们在刚刚的代码中加上这个库的头文件:

2a80f583ef8a4f879b1ee71dcb40c83e.png


因为我们是在客户端完成这个操作所以只需要在client.cc文件中包上这个头文件即可。然后我们修改一下client.cc文件中的代码:


4c45d37877a8445d8f5621d084b7dc0f.png


考虑到大家可能不熟悉getch这个函数,下面我们把这个函数的文档找出来:

b4b909d12d924583bd4b74da54657358.png29140e339102483eb9b82e8910cbaa8c.png

修改完成后下面我们把代码运行起来:

3515f6e1cb31466e80cb0d5c9a4eb24f.png

由于编译不通过是因为我们没有引入client的库,所以我们引入一下:

e2e962760fc74efea85925d9fc03d5fc.pngb6aee63506754781b9b38c0a62e9817c.png


引入后我们重新生成一下可执行文件:

c4cb9a152e2248b2a6a4e970620e6003.png4e3acb6abbf340dbb14b3081e60b44df.png

运行后我们发现服务端不能正常打印了,其实原因在于函数的返回值问题,我们刚刚看文档人家的返回值是int类型,结果我们用char类型接收了,所以就出错了,下面我们修改一下代码:

由于我们不知道返回值是什么,所以我们先在代码中直接打印一下返回值:

51e23124ae444def9a238f616d69e7a9.png

通过打印我们发现返回值为-1:

6da9a16b40674f4d905e122c5394f2b7.png


然后我们将代码修改为当返回值为-1我们就继续读取字符,但是在运行的过程中由于此方法有一些错误导致还是不能成功,所以我们下面直接用系统方法不用库方法:

8a1cafead6ff4839818c74bfb94445de.png


然后我们在服务端接收的时候不打印前面的客户端名称了,直接就是接收什么打印什么(在这里记得刷新缓冲区):

51749b6116f6432b96b7ce0f6bb25409.png

然后下面我们运行起来:

393d9b7091254fd0b683f8ea9ba1c33f.png


这样我们就实现了一开始的功能,通过以上管道的学习相信大家能明白如何创建命名管道以及使用,上面我们使用的系统方法也是从网络上搜的,如果有什么错误还请见谅。


匿名管道与命名管道的区别:

匿名管道由 pipe 函数创建并打开。

命名管道由 mkfififo 函数创建,打开用 open

FIFO (命名管道)与 pipe (匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

命名管道的打开规则:


如果当前打开操作是为读而打开 FIFO 时

O_NONBLOCK disable :阻塞直到有相应进程为写而打开该 FIFO

O_NONBLOCK enable :立刻返回成功

如果当前打开操作是为写而打开 FIFO 时

O_NONBLOCK disable :阻塞直到有相应进程为读而打开该 FIFO

O_NONBLOCK enable :立刻返回失败,错误码为 ENXIO


总结



命名管道可用于同一主机上的任意进程间通信,并且管道通信的本质是通过内核中一块缓冲区(内存)时间数据传输,而命名管道的管道文件只是一个标识符,用于让多个进程能够访问同一块缓冲区,并且管道是半双工通信,是可以选择方向的单向通信。命名管道和匿名有一个相同点,就是他们的本质都是内核中的一块缓冲区。同时补充一点,管道的生命周期是随进程的,本质是内核中的缓冲区,命名管道文件只是标识,用于让多个进程找到同一块缓冲区,删除后,之前已经打开管道的进程依然可以通信。

目录
相关文章
|
2月前
|
NoSQL Linux Redis
linux安装单机版redis详细步骤,及python连接redis案例
这篇文章提供了在Linux系统中安装单机版Redis的详细步骤,并展示了如何配置Redis为systemctl启动,以及使用Python连接Redis进行数据操作的案例。
62 2
|
3月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
137 3
|
3月前
|
存储 Linux 数据处理
在Linux中,什么是管道操作,以及如何使用它?
在Linux中,什么是管道操作,以及如何使用它?
|
3月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
66 0
|
3月前
|
消息中间件 Linux
Linux0.11 管道(十一)
Linux0.11 管道(十一)
25 0
|
3月前
|
数据挖掘 Linux 应用服务中间件
在Linux中,如何在Linux中使用管道?
在Linux中,如何在Linux中使用管道?
|
Linux
Linux命名空间学习教程(五)NET
本文讲的是Linux命名空间学习教程(五)NET,【编者的话】Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。而 LXC所实现的隔离性主要是来自内核的命名空间, 其中pid、net、ipc、mnt、uts 等命名空间将容器的进程、网络、消息、文件系统和hostname 隔离开。
1692 0
|
16天前
|
运维 安全 Linux
Linux中传输文件文件夹的10个scp命令
【10月更文挑战第18天】本文详细介绍了10种利用scp命令在Linux系统中进行文件传输的方法,涵盖基础文件传输、使用密钥认证、复制整个目录、从远程主机复制文件、同时传输多个文件和目录、保持文件权限、跨多台远程主机传输、指定端口及显示传输进度等场景,旨在帮助用户在不同情况下高效安全地完成文件传输任务。
112 5
|
15天前
|
Linux
Linux系统之expr命令的基本使用
【10月更文挑战第18天】Linux系统之expr命令的基本使用
51 4
|
2天前
|
缓存 监控 Linux