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通信 的相关文章

  • 从命名管道读取

    我必须实现一个 打印服务器 我有 1 个客户端文件和 1 个服务器文件 include
  • 除了 iptables 之外还有数据包管理实用程序吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 Linux 实用程序 它可以根据一组规则更改网络数据包的有效负载 理想情况下 我会使用
  • 将用户添加到组但运行“id”时未反映

    R 创建了一个名为 Staff 的组 我希望能够在不以 sudo 身份启动 R 的情况下更新软件包 所以我使用以下方法将自己添加到员工中 sudo usermod G adm dialout cdrom plugdev lpadmin ad
  • 命令行参数中的“-”(破折号)有什么魔力?

    例子 创建 ISO 映像并将其直接刻录到 CD mkisofs V Photos r home vivek photos cdrecord v dev dev dvdrw 更改到上一个目录 cd 侦听端口 12345 并解压发送到该端口的数
  • 页面错误陷阱的成本

    我有一个应用程序 它定期 每 1 或 2 秒后 通过分叉自身来获取检查点 因此 检查点是原始进程的一个分支 它一直保持空闲状态 直到原始进程发生某些错误时被要求启动 现在我的问题是fork的写时复制机制的成本有多大 每当原始进程写入内存页面
  • 如何从 C 文件更改终端中的目录

    如何从 C 程序更改将在终端上生效的目录 实际上不要告诉 system 函数或 chdir 函数 这些仅适用于 C 中的进程或子 shell 假设我正在从 bash shell 执行一个 C 程序 其进程 ID 为 10223 那么 我可以
  • 当存在点和下划线时,使用 sed 搜索并替换

    我该如何更换foo with foo sed 只需运行 sed s foo foo g file php 不起作用 逃离 sed s foo foo g file php Example cat test txt foo bar sed s
  • 如何从脚本向 sudo 提供密码?

    请注意 这是在我的本地计算机上运行的来宾虚拟机 VBox 我不担心安全性 我正在编写一个将在 Linux Ubuntu VM 上执行的脚本myuser用户 该脚本将在下面创建一个非常大的目录树 etc myapp 目前我必须手动完成所有这些
  • 操作系统崩溃的常见原因[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有兴趣了解 操作系统崩溃 不限于Windows崩溃 最常见的技术原因 从操作系统编程的角度 有哪些 我正在寻找一个不像 打开太多应用
  • 在64位操作系统上以32位模式和64位模式编译ioctl函数的执行有什么不同?

    我有 64 位 Enterprise SuSE 11 我有一个应用程序 它打开 HIDRAW 设备并在其上操作 ioctl 函数以从该设备获取原始信息 如下所示 struct hidraw devinfo devinfo int fd op
  • Bash 中 $() 和 () 之间的区别

    当我打字时ls l echo file 支架的输出 这只是简单的回显 被获取并传递到外部ls l命令 就等于简单的ls l file 当我打字时ls l echo file 我们有错误 因为不能嵌套 内部外部命令 有人可以帮助我理解之间的区
  • 从 Linux 命令行发送 SNMP 陷阱消息

    Folks 我需要从 Linux 命令行使用此命令 snmptrap 将自定义消息发送到陷阱侦听器 我需要根据用户设置在 v1 和 v2c 中发送相同的消息 这是我发现的 For v1 snmptrap v 1 c Tas hostname
  • 是否可以找到哪个用户位于 localhost TCP 连接的另一端?

    这是一个编程问题 但它是 Linux Unix 特定的 如果我从本地主机获得 TCP 连接 是否有一种简单的方法可以告诉哪个用户在 C 程序内建立了连接而无需 shell 我知道这对于 Unix 域套接字来说并不太难 我已经知道远程 IP
  • Alsa 带有来自调制解调器的 PCM 接口

    我有一个基于 imx28 CPU 的定制板 CPU 的串行端口连接到调制解调器的 PCM 输出 我必须为调制解调器的 PCM 接口开发一个驱动程序 使其成为 ALSA SoC 的一部分 您能指出内核树 中与我的设置重新组合的一些驱动程序吗
  • 通过 SSH 将变量传递给远程脚本

    我正在通过 SSH 从本地服务器在远程服务器上运行脚本 首先使用 SCP 复制该脚本 然后在传递一些参数时调用该脚本 如下所示 scp path to script server example org another path ssh s
  • UDP 广播发送失败:在 Linux 2.6.30 上“网络无法访问”

    我用udp广播写了一个程序 代码段如下 struct sockaddr in broadcast addr socklen t sock len sizeof broadcast addr bzero broadcast addr sock
  • 如何使用ffmpeg重叠和合并多个音频文件?

    我正在尝试将多个音频文件合并到一个文件中 但我可以使用以下命令来连接 而不是连接 ffmpeg v debug i file1 wav i file2 wav i file3 wav filter complex 0 0 concat n
  • Linux 文本文件操作

    我有一个格式的文件 a href a href a href a href 我需要选择 之后但 之前的文本 并将其打印在行尾 添加后 例如 a href http www wowhead com search Su a a a a a
  • 如何在 Linux x86_64 上模拟 iret

    我正在编写一个基于 Intel VT 的调试器 由于当 NMI Exiting 1 时 iret 指令在 vmx guest 中的性能发生了变化 所以我应该自己处理vmx主机中的NMI 否则 guest会出现nmi可重入错误 我查了英特尔手
  • 使用命令行将 MediaWiki 维基文本格式转换为 HTML

    我倾向于编写大量文档 因此 MediaWiki 格式对我来说很容易理解 而且比编写传统 HTML 节省了我很多时间 然而 我也写了一篇博客 发现一直从键盘切换到鼠标来输入正确的 HTML 标签会增加很多时间 我希望能够使用 Mediawik

随机推荐

  • 记录错误: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 在子进程中进行客