Linux实现多进程服务端Socket通信

2023-11-17

目录

程序流程

程序实例

运行结果


本例主要是让服务器能够同时处理多个客户端的连接请求。

程序流程

1. 创建基本的套接字,并绑定地址信息、设置监听;

2. 循环accept来接收连接请求,每接收一个连接请求,就创建一个子进程;

3. 在子进程中进行客户端与服务端的数据通信;

4. 在父进程中定义一个消息处理程序,用来等待子进程结束,从而防止僵尸进程的产生。

程序实例

#include<iostream>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<errno.h>
#include<signal.h>
#include<sys/socket.h>
#include<sys/wait.h>

using namespace std;

#define SERV_IP "127.1.2.3"
#define SERV_PORT 8888

struct socket_info   //将文件描述符与地址结构体绑定在一起
{
	struct sockaddr_in sktaddr;
	int fd;
};


void sigChild(int sig)   //消息处理函数,当子进程退出时执行,用来回收子进程,防止僵尸进程
{
	while(waitpid(-1,NULL,WNOHANG) > 0);   //最后一个参数用WNOHANG,意味父进程非阻塞式等待子进程结束
}

int main()
{
	socket_info listenskt,connskt;  //一个用于服务端监听,一个用于服务端收发
	pid_t pid;
	socklen_t clit_size ;
	
        //注册信号,使用sigaction
	struct sigaction newac; //先创建一个sigaction结构体,用来封装信号的处理方式,掩码等信息
	newac.sa_handler = sigChild;   //指定信号发生时调用句柄(用函数名即可)
	sigemptyset(&newac.sa_mask);  //清空掩码,掩码为空表示无屏蔽信号
	newac.sa_flags = 0;
	sigaction(SIGCHLD,&newac,NULL);    //注册信号

	memset(&listenskt,0,sizeof(listenskt)); //置0
	memset(&connskt,0,sizeof(connskt));

	if((listenskt.fd = socket(AF_INET,SOCK_STREAM,0)) == -1)  //创建套接字
	{
		cout<<"socket create failed : "<<strerror(errno)<<endl;
		return 0;
	}
        //绑定地址信息
	listenskt.sktaddr.sin_family = AF_INET;
	listenskt.sktaddr.sin_port = htons(SERV_PORT);
	listenskt.sktaddr.sin_addr.s_addr = inet_addr(SERV_IP);

	if(bind(listenskt.fd,(sockaddr *)&listenskt.sktaddr,sizeof(listenskt.sktaddr)) == -1 )   //绑定
	{
		cout<<"bind error : "<<strerror(errno)<<endl;
		return 0;
	}

	if(listen(listenskt.fd,100) == -1)  //监听
	{
		cout<<"listen error : "<<strerror(errno)<<endl;
		return 0;	
	}
 		
	cout<<"Init Success ! "<<endl;
	cout<<"host ip : "<<inet_ntoa(listenskt.sktaddr.sin_addr)<<"  port : "<<ntohs(listenskt.sktaddr.sin_port)<<endl;

	cout<<"Waiting for connections ... "<<endl;

	while(1)
	{
		clit_size = sizeof(connskt.sktaddr);
		if( (connskt.fd = accept(listenskt.fd,(sockaddr *)&connskt.sktaddr,&clit_size) ) == -1 ) //阻塞接收连接请求
		{
			if(errno == EINTR)continue ;  
                         /*必须加上这一句,当一个客户端断开时(比如说按下CTRL+C),
                           父进程和子进程都会引发中断异常,也就是这里的EINTR,父进
                           程通过这句话来重新accept,不然就会直接退出*/
			cout<<"accept error : "<<strerror(errno)<<endl;
			return 0;
		}
                //连接成功
		cout<<inet_ntoa(connskt.sktaddr.sin_addr)<<":"<<ntohs(connskt.sktaddr.sin_port)<<" connected ...  "<<endl; //显示连接客户端信息
		//创建进程
		if((pid = fork()) == 0)   //子进程
		{
			close(listenskt.fd);  //子进程中监听套接字无用,直接关闭	
    		        while(1)  //进行数据接收
			{
				char buf[1024];
				int readstate = read(connskt.fd,buf,sizeof(buf));
				if(readstate == 0)
				{
					cout<<inet_ntoa(connskt.sktaddr.sin_addr)<<":"<<ntohs(connskt.sktaddr.sin_port)<<" exit ... "<<endl;
					break;
				}
                                else if(readstate < 0)
                                {
                                    cout<<"connect error : "<<strerror(errno)<<endl;
                                    break;
                                }
				write(STDOUT_FILENO,buf,readstate); //显示收到的信息
				cout<<"      (From "<<inet_ntoa(connskt.sktaddr.sin_addr)<<":"<<ntohs(connskt.sktaddr.sin_port) <<")"<<endl;   //显示信息源地址
				for(int i=0;i<readstate;i++)
					buf[i] = toupper(buf[i]);  // 转为大写后发回
				write(connskt.fd,buf,readstate);		
			}
			close(connskt.fd);  //子进程结束前关闭连接
			return 0;  //子进程退出
		}
		else if(pid > 0)  //父进程
		{
			close(connskt.fd);
		}
		else  //进程创建失败
		{
			cout<<"fork error : "<<strerror(errno)<<endl;
		}
	}

	return 0;

}

运行结果

客户端依旧使用之前的,先运行服务器:

然后再新建多个终端,运行多个客户端:(左上为服务端,其余三个为客户端)

然后在客户端发送消息测试:

 客户端退出:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux实现多进程服务端Socket通信 的相关文章

  • 如何使用 JSch 将多行命令输出存储到变量中

    所以 我有一段很好的代码 我很难理解 它允许我向我的服务器发送命令 并获得一行响应 该代码有效 但我想从服务器返回多行 主要类是 JSch jSch new JSch MyUserInfo ui new MyUserInfo String
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • ALSA:snd_pcm_writei 调用时缓冲区不足

    当运行我最近从灰烬中带回来的旧程序时 我遇到了缓冲区不足的情况 该程序将原始声音文件完全加载到内存中 2100 字节长 525 帧 并准备 ALSA 进行输出 44 1khz 2 通道 有符号 16 位 if err snd pcm set
  • docker 非 root 绑定安装权限,WITH --userns-remap

    all 尝试让绑定安装权限正常工作 我的目标是在容器中绑定安装卷 以便 a 容器不以 root 用户身份运行入口点 二 docker daemon 配置了 userns remap 这样容器 主机上没有 root c 我可以绑定挂载和读 写
  • 我们真的应该使用 Chef 来管理 sudoers 文件吗?

    这是我的问题 我担心如果 Chef 破坏了 sudoers 文件中的某些内容 可能是 Chef 用户错误地使用了说明书 那么服务器将完全无法访问 我讨厌我们完全失去客户的生产服务器 因为我们弄乱了 sudoers 文件并且无法再通过 ssh
  • 就分页分段内存而言的程序寿命

    我对 x86 Linux 机器中的分段和分页过程有一个令人困惑的概念 如果有人能澄清从开始到结束所涉及的所有步骤 我们将很高兴 x86 使用分页分段内存技术进行内存管理 任何人都可以解释一下从可执行的 elf 格式文件从硬盘加载到主内存到它
  • 执行“minikube start”命令时出现问题

    malik malik minikube start minikube v1 12 0 on Ubuntu 18 04 Using the docker driver based on existing profile Starting c
  • 如何在linux中以编程方式获取dir的大小?

    我想通过 C 程序获取 linux 中特定目录的确切大小 我尝试使用 statfs path struct statfs 但它没有给出确切的大小 我也尝试过 stat 但它返回任何目录的大小为 4096 请建议我如何获取 dir 的确切大小
  • C 语言的符号表

    我目前正在开发一种执行模式匹配的静态分析工具 我在用Flex https github com westes flex生成词法分析器 我编写了代码来管理符号表 我不太有经验C 所以我决定将符号表实现为线性链表 include
  • 使用循环在 C 中管道传输两个或多个 shell 命令

    我正在尝试执行ls wc l通过 C 语言程序 而不是使用命令行 这是我当前的工作代码 int main int pfds 2 pipe pfds pid t pid fork if pid 0 The child process clos
  • 并行运行 shell 脚本

    我有一个 shell 脚本 打乱大型文本文件 600 万行和 6 列 根据第一列对文件进行排序 输出 1000 个文件 所以伪代码看起来像这样 file1 sh bin bash for i in seq 1 1000 do Generat
  • CMake 链接 glfw3 lib 错误

    我正在使用 CLion 并且正在使用 glfw3 库编写一个程序 http www glfw org docs latest http www glfw org docs latest 我安装并正确执行了库中的所有操作 我有 a 和 h 文
  • 使用 shell 脚本将行附加到 /etc/hosts 文件

    我有一个新的 Ubuntu 12 04 VPS 我正在尝试编写一个安装脚本来完成整个 LAMP 安装 我遇到问题的地方是在 etc hosts文件 我当前的主机文件如下所示 127 0 0 1 localhost Venus The fol
  • Bash - 在与当前终端分开的另一个终端中启动命令的新实例

    我有一个简单的 bash 脚本 test sh 设置如下 bin bash args if args 0 check capture then watch n 1 ls lag home user capture0 watch n 1 ls
  • 如何使用waf构建共享库?

    我想使用构建一个共享库waf http code google com p waf 因为它看起来比 GNU 自动工具更容易 更简洁 到目前为止 我实际上有几个与我开始编写的 wscript 有关的问题 VERSION 0 0 1 APPNA
  • 如何在 Linux 中使用 C 语言使用共享内存

    我的一个项目有点问题 我一直在试图找到一个有据可查的使用共享内存的例子fork 但没有成功 基本上情况是 当用户启动程序时 我需要在共享内存中存储两个值 当前路径这是一个char and a 文件名这也是char 根据命令参数 启动一个新进
  • 使用 python 脚本更改 shell 中的工作目录

    我想实现一个用户态命令 它将采用其参数之一 路径 并将目录更改为该目录 程序完成后 我希望 shell 位于该目录中 所以我想实施cd命令 但需要外部程序 可以在 python 脚本中完成还是我必须编写 bash 包装器 Example t
  • 使用 gdb 调试 Linux 内核模块

    我想知道 API 在内核模块 中返回什么 从几种形式可以知道 这并不是那么简单 我们需要加载符号表来调试内核模块 所以我所做的就是 1 尝试找到内核模块的 text bss和 data段地址 2 在 gdb 中使用 add symbol f
  • 这种文件锁定方法可以接受吗?

    我们有 10 个 Linux 机器 每周必须运行 100 个不同的任务 这些计算机主要在我们晚上在家时执行这些任务 我的一位同事正在开发一个项目 通过使用 Python 自动启动任务来优化运行时间 他的程序将读取任务列表 抓取一个打开的任务
  • 如何在 Mac OSX Mavericks 中正确运行字符串工具?

    如何在 Mac OSX Mavericks 中正确运行字符串工具 我尝试按照我在网上找到的示例来运行它 strings a UserParser class 但我收到此错误 错误 Applications Xcode app Content

随机推荐

  • 记录错误:con not perform the following tasks

    Ubuntu系统下安装软件出现报错 con not perform the following tasks TOC 检查软件源 实在不行改为国内源 或者等待网络再次下载
  • Bootstarp4 设计网页轮播组件

    很多网站都有广告轮播功能 可使用bootstrap4中的carousel组件非常简单的实现 目录 下载bootstrap4 轮播功能实现 简单实现轮播组件 增加标识图标 增加标题和说明 切换淡入淡出 设置数据间隔 总结 下载bootstra
  • 基于微信云开发实现电影推荐小程序

    一 项目背景 项目名称为柚子电影 此小程序的目的是为了给大家推荐电影 与其他的售票等小程序不同 二 性能需求 我的影单的增加 删除和查询 电影详情页面的完整实现 对小程序的各个方面 电影推荐 电影详情 用户授权 影院查询 影院位置 用户登录
  • Scala(一):概述&变量&流程控制(转载)

    文章目录 一 简介 1 1 scala语言的特点 1 2 第一个scala程序 二 变量 2 1 Scala变量的使用 2 2 Scala数据类型 2 3 值类型转换 三 循环控制 3 1 分支控制if else 3 2 for循环控制 S
  • opencv4应用开发基础

    opencv3 0版本以上都是用C 实现的 常用的一些函数及类型集中在cv命名空间里 cv Mat类型用于表示一个图像 构造函数除了空的构造函数外 还有很多个 Mat int rows int cols int type 创建指定行 列数的
  • springcloud常见面试题(2023最新)

    目录 前言 一 微服务 1 微服务是什么 2 你知道哪些RPC框架 3 springCloud和Dubbo有什么区别 4 SpringCloud由什么组成 二 Spring Cloud Eureka 1 Eureka包含几个组件 2 Eur
  • 探究Android SQLite3多线程

    http www cnblogs com xyczero p 4096297 html 最近做项目时在多线程读写数据库时抛出了异常 这自然是我对SQlite3有理解不到位的地方 所以事后仔细探究了一番 关于getWriteableDataB
  • visio增加连接点

    在画系统架构图的时候遇到一个问题 如果一个图形本来有的连接点不够 需要在任何的位置上增加连接点 看了很多网络介绍 但是总是增加不成功 继续发现接下来问题揭晓 2013版本visio举例 首先在开始中找到连接点 其次 按住ctrl键 在想要添
  • CBOW 与 skip-gram

    skip gram是利用中间词预测邻近词 cbow是利用上下文词预测中间词 一 CBOW 1 continues bag of words 其本质是通过context来预测word CBOW之所以叫连续词袋模型 是因为在每个窗口内它也不考虑
  • Sublime Text自定义配色方案

    先推荐介绍几款非常好用的自定义主题 https github com aziz tmTheme Editor http tmtheme editor herokuapp com 这个可以在线修改配色方案 也可以上传本地的方案修改 https
  • linux源码文件数量,Linux 下统计文件夹大小及文件数量

    查看文件夹大小 lib 目录大小 du sh lib lib 子目录大小 du sh lib 查看 lib 目录下普通文件大小 find lib type f xargs ls la awk F BEGIN sum 0 sum 5 END
  • prim算法解决最小生成树问题

    刚好这次又遇到了prim算法 就做了下整理 可以参考 数据结构与算法分析c 描述 这本书 个人而言 很经典 并把以前写的代码也整理了一下 做下分享 同时也加深下自己的理解 prim算法是解决最小生成树问题的一个很好的算法 此算法是是将点集合
  • iOS - 常用的宏定义

    1 处理NSLog事件 开发者模式打印 发布者模式不打印 ifdef DEBUG define NSLog FORMAT fprintf stderr s d t s n NSString stringWithUTF8String FILE
  • 第九章 Qt拖放

    拖放是Qt实现的应用程序内或者多个应用程序之间传递信息的一种直观的现代操作方式 有没有想到windows的剪贴板 数据的移动和复制功能都异曲同工嘞 一 使拖放生效 拖放包含两个动作 拖动 和 放下 Qt窗口部件可以作为拖动点 drag si
  • NestedScrollView + RecyclerView完美解决显示不全及滑动冲突

  • color属性 python_Python cv2.CV_LOAD_IMAGE_COLOR属性代码示例

    需要导入模块 import cv2 as 别名 或者 from cv2 import CV LOAD IMAGE COLOR as 别名 def load cv2 img grayscale None TODO load images if
  • Hive连接报错,显示用户没有权限 org.apache.hadoop.ipc.RemoteException:User: xxx is not allowed to impersonate root

    Hive连接报错 显示用户没有权限 org apache hadoop ipc RemoteException User xxx is not allowed to impersonate root org apache hadoop ip
  • docker学习使用文档

    docker学习参考文档 学习途径 安装 介绍 环境准备 开始安装 卸载依赖 删除资源 阿里云镜像加速 底层原理 docker怎么工作 docker为什么比虚拟机快 1 docker有着比虚拟机更少的抽象层 2 docker利用的是宿主机内
  • 安卓ui开发教程下载!被面试官问的Android问题难倒了,内容太过真实

    前言 这些题目是网友去百度 小米 乐视 美团 58 猎豹 360 新浪 搜狐等一线互联网公司面试被问到的题目 熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率 欢迎一线公司员工以及网友提交面试题库 欢迎留言 网上的都是按照公司划分的
  • Linux实现多进程服务端Socket通信

    目录 程序流程 程序实例 运行结果 本例主要是让服务器能够同时处理多个客户端的连接请求 程序流程 1 创建基本的套接字 并绑定地址信息 设置监听 2 循环accept来接收连接请求 每接收一个连接请求 就创建一个子进程 3 在子进程中进行客