Unix网络编程学习日记(三):多进程全双工socket客户端的实现

本文档详细介绍了如何在Unix环境下实现一个多进程全双工的socket客户端,涵盖总述、设计、模块实现、数据结构、用户界面设计以及容灾策略。客户端使用TCP连接服务器,通过键盘指令控制操作,如连接、断开、发送消息和文件。设计中采用信号、管道和消息队列进行进程间通信,确保高效响应。
摘要由CSDN通过智能技术生成

本程序其实写在上两篇博客的程序之前,思想更不成熟,代码更冗杂,bug也可能更多。使用父子进程的方式实现多线程可以实现的功能有些多此一举,事实上本程序的代码量是上一篇中多线程实现的三倍,内存占用是两倍有余。
不过有趣的一点是,这个小程序让我练习了三种进程间通信方法:信号、管道、消息队列。

一、总述

本设计为一网络通信客户端程序,实现以下要求:
1、通过网络连接PC上运行的服务器程序,服务器测试程序不用实现,暂时不用考虑服务器给设备的应答。
2、使用TCP方式连接。
3、客户端端可以通过串口输入指令控制客户端操作。控制指令包含:连接服务器、断开服务器、给服务器发测试语句、给服务器发送一个小文件。
4、客户端可以接受服务器下发的数据打印显示并保存成文件

二、总体设计

本设计的网络、文件操作基于Linux标准库函数,因此具有较强的可移植性,在x86平台、ARM平台均可良好运行。程序分为一个负责接收键盘指令、数据显示、数据存储的主进程,和两个负责接收、读取socket包的子进程。子进程没有任务时均处于阻塞状态,进程间同步由信号和管道的阻塞机制实现,耗费资源较少,且在网络通信请求产生时能够快速响应。接收到的信息形式暂存在链表中,需要储存时出队并以基于行的IO形式存入文件。

三、模块设计

1、信息接收模块

该模块实体为RecvProc,实现了socket包的接收、显示、通知主模块处理的功能。
与主模块间单工异步通信,使用信号和消息队列两种IPC机制。该模块收到socket包时,先和时间戳绑定后存入消息队列,再通过用户自定义信号通知主进程处理消息队列。
这里写图片描述

2、信息发送模块

该模块实体为SendProc,实现了socket包的发送功能。
与主模块间单工同步通信,使用了匿名管道机制。该模块无任务时由匿名管道的read函数实现阻塞,当主模块需要发送消息时,管道连通,阻塞解除。发送子进程读取管道中的待发送信息,传递给send函数发送
这里写图片描述

3、主模块

该模块实体为MainProc,为1、2两子进程的父进程,实现了进程调度、接收键盘指令、数据显示、数据存储等功能。
程序启动时,该模块首先初始化,得到socket、消息队列等资源的描述符,再经由发送、接收模块的构造函数传递给两模块。两模块初始化完成后,由主模块创建子进程,在子进程中运行两模块的业务功能。
这里写图片描述

四、数据结构

本设计使用单向队列暂存接收到的数据,容器为deque。具有首尾数据读写效率高,数据存储在内存中分块,利于大量存储的特点。
这里写图片描述
这里写图片描述

五、用户界面设计

本设计使用命令行进行操作,在程序运行时,提示用户输入服务器ip和端口
remote ip:192.168.51.89
remote port:2345

1、连接服务器

若连接成功则提示

connected successfully 192.168.51.89:2345

否则,则提示错误并显示错误原因,如:
connect error!: Connection refused

2、功能选项

连接成功后,显示功能选项:

1.save the message in buffer into a file
2.send message to the server
3.send file to the server
0.disconnect to the server

当光标前标有“[command]”时,可输入以上选项进入相应功能。亦可输入“?”重新显示该菜单。

3.接收消息

程序启动后,接收进程始终在后台运行。当接收到服务器消息后,消息立即在屏幕显示,以[recv]开头,并附有接收时间。如:

[recv][20170807 10:52:19] test message

4.储存消息

选择选项“1”即进入储存消息功能。此时光标前提示“[path]”,在此输入储存消息的文件路径并回车。若文件不存在则自动生成。然后,屏幕中会显示文件写入的内容,如:

[path]/tmp/output.txt

write:20170807 10:52:19 test message write:20170807 10:53:50
test message again

write file complete!

5.发送消息

选择选项“2”即进入发送消息功能。此时光标前提示“[msg]”,在此输入待发送的消息并回车,如:

[msg]test message

6.发送文件

选择选项“3”即进入储存消息功能。此时光标前提示“[path]”,在此输入待发送的文件路径并回车。若文件不存或无读取权限则由相应提示,如:

read the file to be send failed: No such file or directory

若读取成功,则输出读取文件并发送的内容,如:

openfile success [send]#BEGIN# [send]20170807 08:36:49 987
[send]20170807 08:36:50 654 [send]20170807 08:36:51 321
[send]20170807 10:52:19 test message [send]20170807 10:53:50
test message again [send]#EOF#

其中,首尾两条并非文件内容,是为将文件与普通消息相区别的标识符。

7.退出程序

选择选项“0”即则退出程序。此时程序会结束子进程,清理系统资源并退出。

六、容灾设计

1.程序被强行终止

为防止程序在终端被用户使用CTRL+C强行终止,导致系统资源没有及时释放,本设计捕捉了SIGINT信号,接收到信号时激活各模块的析构函数,保证释放系统资源、回收垃圾后退出。

2.功能选项输入错误

若功能选项输入错误,则要求用户重新输入

3.参数输入错误

当输入传递给系统函数的参数输入错误,例如文件路径、ip地址等错误时,输出系统维护的错误代码对应的错误提示,并退出当前函数,防止段错误等异常情况发生。


main.c

#include "main_proc.h"
#include "recv_proc.h"
#include "send_proc.h"

MainProc *mainProc;
RecvProc 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值