C++在Linux实现多线程和多进程的TCP服务器和客户端通信

多进程版本

服务器

#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <string>
void mywait(int num)
{while(1){pid_t pid=waitpid(-1,NULL,WNOHANG);//非阻塞回收进程if(pid>0)printf("回收了%d\n",pid);if(pid==0||pid==-1)break;}
}
int main()
{int flag=0;struct sockaddr_in saddr;saddr.sin_port = htons(8999);saddr.sin_addr.s_addr = INADDR_ANY;saddr.sin_family = AF_INET;int sfd = socket(AF_INET, SOCK_STREAM, 0);struct sigaction sig;sigemptyset(&sig.sa_mask);sig.sa_flags=0;sig.sa_handler=mywait;sigaction(SIGCHLD,&sig,NULL);//设置SIGCHLD信号捕捉if (sfd == -1){perror("socket error");return 1;}flag = bind(sfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));if (flag == -1){perror("bind error");return 1;}flag=listen(sfd, 100);if(flag==-1){perror("listen error");return 1;}struct sockaddr_in caddr;int clen=sizeof(caddr);while (1){int cfd = accept(sfd, (struct sockaddr*)&caddr, (socklen_t*)&clen);if (cfd == -1){perror("accept error");continue;}char ip[1024]={'\0'};//必须加上,不然解析IP会失败printf("接收到了客户端%s:%d的连接\n",inet_ntop(AF_INET,&caddr.sin_addr,ip,1024),ntohs(caddr.sin_port));int pid=fork();if(pid==0){close(sfd);while(1){char buf[1024] = {'\0'};flag = recv(cfd, buf, 1024, 0);if (flag==-1){perror("read error");break;}else if(flag==0){printf("连接断开\n");break;}printf("从客户端收到数据:%s\n", buf);std::string sendstr="服务器收到了"+std::to_string(caddr.sin_port)+"的数据";flag = send(cfd, sendstr.c_str(), sendstr.length(), 0);if (flag == -1){perror("send error");break;}memset(buf, 0, 1024);}exit(0);}else{close(cfd);}}return 0;
}

客户端

#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string>
int main()
{int flag;struct sockaddr_in* caddr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));inet_pton(AF_INET, "192.168.101.231", &caddr->sin_addr.s_addr);caddr->sin_family = AF_INET;caddr->sin_port = htons(8999);int cfd = socket(AF_INET, SOCK_STREAM, 0);if (cfd == -1){perror("socket error");return 1;}flag= connect(cfd, (struct sockaddr*)caddr, sizeof(struct sockaddr));//caddr就是指针类型if (flag == -1){perror("connect error");return 1;}int i=0;while (1){char buf[1024] = {'\0'};std::string sendstr="我是客户端,我发送了"+std::to_string(i);flag = send(cfd,  sendstr.c_str(), sendstr.length(),0);if (flag == -1){perror("send error");continue;}printf("send:%s\n", sendstr.c_str());flag = recv(cfd, buf, 1024, 0);if (flag == -1){perror("recv error");continue;}printf("客户端收到数据:%s\n", buf);memset(buf, 0, 1024);i++;sleep(1);}close(cfd);return 0;
}

多线程版本服务器

#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string>
#include <pthread.h>
void* handle(void* arg)
{int flag=0;int* arr=(int*)arg;int cfd=arr[0];int port=arr[1];while(1){char buf[1024] = {'\0'};flag = recv(cfd, buf, 1024, 0);if (flag==-1){perror("read error");break;}else if(flag==0){printf("连接断开\n");break;}printf("从客户端%d收到数据:%s\n",port,buf);std::string sendstr="服务器收到了"+std::to_string(port)+"的数据";flag = send(cfd, sendstr.c_str(), sendstr.length(), 0);if (flag == -1){perror("send error");break;}memset(buf, 0, 1024);}close(cfd);return NULL;
}
int main()
{int flag=0;struct sockaddr_in saddr;saddr.sin_port = htons(8999);saddr.sin_addr.s_addr = INADDR_ANY;saddr.sin_family = AF_INET;int sfd = socket(AF_INET, SOCK_STREAM, 0);if (sfd == -1){perror("socket error");return 1;}flag = bind(sfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));if (flag == -1){perror("bind error");return 1;}flag=listen(sfd, 100);if(flag==-1){perror("listen error");return 1;}while (1){struct sockaddr_in caddr;int clen=sizeof(caddr);int cfd = accept(sfd, (struct sockaddr*)&caddr, (socklen_t*)&clen);int port=ntohs(caddr.sin_port);printf("端口号:%d\n",port);if (cfd == -1){perror("accept error");continue;}char ip[1024]={'\0'};//必须加上,不然解析IP会失败printf("接收到了客户端%s:%d的连接\n",inet_ntop(AF_INET,&caddr.sin_addr,ip,1024),port);pthread_t tid;int arg[2]={cfd,port};pthread_create(&tid,NULL,handle,(void*)arg);//这里不能传递cfd的地址,各个线程是共享这个地址的pthread_detach(tid);}return 0;
}

 运行效果:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uni-app和Node.js使用uni-push2.0实现通知栏消息推送功能

前言 uniapp 提供了 unipush 统一推送服务,但是每次要推送消息的时候都要登陆 Dcloud 开发者后台&#xff0c;有点不方便&#xff0c;运营需要在我们的后台系统就可以完成操作。 效果演示 消息下发流程 名词解释 名词解释通知消息指定通知标题和内容后&#xff0c;由个推 SD…

电脑上如何多开微信软件(多个微信同时使用)

想登录几个就下面这种文件里&#xff0c;复制几行即可&#xff1a; 创建的是以 .bat 文件结尾的txt文件&#xff08;先创建一个txt文本文档&#xff0c;等写好了命令保存后&#xff0c;再把文件的后缀名改为: .bat &#xff09;再保存即可。然后&#xff0c;右键以管理员运行&a…

炫酷HTML蜘蛛侠登录页面

全篇使用HTML、CSS、JavaScript&#xff0c;建议有过基础的进行阅读。 一、预览图 二、HTML代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-w…

C语言的结构体类型

在我们使用C语言进行编写代码时&#xff0c;常常会使用已经给定的类型来创建变量&#xff0c;比如int型&#xff0c;char型&#xff0c;double型等&#xff0c;而当我们想创建一些较为复杂的东西时&#xff0c;单单用一个类型变量是没办法做到的&#xff0c;比如我们想创建一个…

DPDK基础入门(十):虚拟化

I/O虚拟化 全虚拟化&#xff1a;宿主机截获客户机对I/O设备的访问请求&#xff0c;然后通过软件模拟真实的硬件。这种方式对客户机而言非常透明&#xff0c;无需考虑底层硬件的情况&#xff0c;不需要修改操作系统。 半虚拟化&#xff1a;通过前端驱动/后端驱动模拟实现I/O虚拟…

嵌入式鸿蒙系统开发语言与开发方法分析

大家好,今天主要给大家分享一下,HarmonyOS系统的主力开发语言ArkTS语言开发方法,它是基于TypeScript(简称TS)语言扩展而来。 第一:ArkTS语言基本特性 目的:声明式UI,让开发者以更简洁,更自然的方式开发高性能应用。 声明式 UI基本特性: 基本UI描述:ArkTS定义了各种装饰…

使用Ubuntu耳机输出正弦波信号

最近有一个项目想使用喇叭发出一个标准的正弦波测试信号&#xff0c;故记录下操作过程 sudo apt install libasound2-dev 否则有可能会报错&#xff1a; alsaaudio.c:28:10: fatal error: alsa/asoundlib.h: No such file or directory 安装pyalsaaudio&#xff1a; pip …

合肥鲸天科技的外卖会员卡系统有人做过吗?赚钱吗?

我们先来了解一下这个合肥鲸天科技&#xff0c;通过我在网上找到的资料和企业查询&#xff0c;这家公司还是很有实力的&#xff0c;合肥鲸天科技有限公司也是欢迎有合作的人到公司来进行一个考察和合作其他一些项目的。 外卖会员卡简介绍&#xff1a; 这个外卖会员卡&#xf…

Linux | 探索 Linux 信号机制:信号的产生和自定义捕捉

信号是 Linux 操作系统中非常重要的进程控制机制&#xff0c;用来异步通知进程发生某种事件。理解信号的产生、阻塞、递达、捕捉等概念&#xff0c;可以帮助开发者更好地编写健壮的应用程序&#xff0c;避免由于未处理的信号导致程序异常退出。本文将带你从基础概念开始&#x…

Redis Key的过期策略

Redis 的过期策略主要是指管理和删除那些设定了过期时间的键&#xff0c;以确保内存的有效使用和数据的及时清理。 具体来说&#xff0c;Redis 有三种主要的过期策略&#xff1a;定期删除&#xff08;Scheduled Deletion&#xff09;、惰性删除&#xff08;Lazy Deletion&#…

C#命令行参数解析库System.CommandLine介绍

命令行参数 平常在日常的开发过程中&#xff0c;会经常用到命令行工具。如cmd下的各种命令。 以下为sc命令执行后的截图&#xff0c;可以看到&#xff0c;由于没有输入任何附带参数&#xff0c;所以程序并未执行任何操作&#xff0c;只是输出了描述和用法。 系统在创建一个新…

【BFS专题】— 解决最短路问题

1、迷宫中离入口最近的出口 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 利用BFS层序遍历&#xff0c;新建一个变量统计步数代码&#xff1a; class Solution {int dx[] {0, 0, -1, 1};int dy[] {1, -1, 0, 0};public int nearestExit(char[][] maze, int[] en…

URP 线性空间 ui资源制作规范

前言&#xff1a; 关于颜色空间的介绍&#xff0c;可参阅 unity 文档 Color space URP实现了基于物理的渲染&#xff0c;为了保证光照计算的准确&#xff0c;需要使用线性空间&#xff1b; 使用线性空间会带来一个问题&#xff0c;ui资源在unity中进行透明度混合时&#xff…

Centos7 Hadoop 单机版安装教程(图文)

本章教程,主要记录如何在Centos7中安装Hadoop单机版。 一、软件安装包和基础环境 CentOS7.x,jdk8,hadoop 通过网盘分享的文件:Hadoop 链接: https://pan.baidu.com/s/1_qGI9QeXMAJNb3TydHhQGA?pwd=xnz4 提取码: xnz4 当然你也可以自己去官网下载。 java8:https://www.ora…

Redis:发布(pub)与订阅(sub)实战

前言 Redis发布订阅&#xff08;Pub/Sub&#xff09;是Redis提供的一种消息传递机制&#xff0c;它使用“发布者-订阅者”&#xff08;publisher-subscriber&#xff09;模式来处理消息传递。在这种模式下&#xff0c;发布者将消息发布到一组订阅者中&#xff0c;而无需关心谁…

java的内存分配和回收机制

Java 与 C之间有一堵由内存动态分配和垃圾收集技术所围成的高墙&#xff0c;墙外面的人想进去&#xff0c;墙里面的人却想出来。 概述 垃圾收集&#xff08;GC&#xff09;需要完成的三件事情&#xff1a; 哪些内存需要回收&#xff1f;什么时候回收&#xff1f;如何回收&am…

Linux操作系统入门(三)

_______________________________________________ 一.Linux操作系统的文件结构 相比于Windows操作系统的C,D,E等盘符&#xff0c;Linux操作系统仅有一个"/"符号的根目录. 这其中存在一个显著的不同&#xff0c;Linux操作系统使用的是斜杠"/",而Windows…

基于微信小程序的宠物之家的设计与实现

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于微信小程序JavaSpringBootVueMySQL的宠物之家/宠物综合…

判断当前环境是否为docker容器下

判断当前环境是否为docker容器下 webshell后或登录到系统后台&#xff0c;判断是否为docker容器可使用如下方法&#xff1a; 方式一&#xff1a;使用ls -alh命令查看是否存在.dockerenv来判断是否在docker容器环境内 ls -alh /.dockerenv如下图无.dockerenv文件&#xff0c;所…

本地部署轻量级web开发框架Flask结合内网穿透公网环境访问管理界面

文章目录 1. 安装部署Flask2. 安装Cpolar内网穿透3. 配置Flask的web界面公网访问地址4. 公网远程访问Flask的web界面 本篇文章主要讲解如何在本地安装Flask&#xff0c;以及如何将其web界面发布到公网进行远程访问。 Flask是目前十分流行的web框架&#xff0c;采用Python编程语…