基于LinuxC语言实现的TCP多线程/进程服务器

多进程并发服务器

设计流程

框架一(使用信号回收僵尸进程)

void handler(int sig)
{while(waitpid(-1, NULL, WNOHANG) > 0);
}int main()
{//回收僵尸进程siganl(17, handler);//创建服务器监听套接字 serverserver = socket();//给服务器地址信息结构体赋值,并绑定bind();//监听指定端口,设置监听队列listen();while(1){//创建与客户端通信的套接字client = accept();//创建子进程if(fork() == 0){//关闭拷贝的服务器套接字close(server);while(1){//接收消息recv();//发送消息send();}//通信结束关闭套接字close(client);//退出进程exit(0);}//关闭父进程的通信套接字close(client);}//服务器关闭close(server);
}

实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s);void cil(int client, struct sockaddr_in caddr);void handler(int sig)
{while(waitpid(-1, NULL, WNOHANG) > 0);
}int main(int argc, char *argv[])
{//回收僵尸进程signal(17, handler);//创建服务器int server = -1;if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1){LOG("socket error");return -1;}//给服务器地址信息结构体赋值,并绑定struct sockaddr_in saddr = {0};saddr.sin_family = AF_INET;saddr.sin_port = htons(8888);saddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1){LOG("bind error");return -1;}//监听指定端口,设置监听队列if(listen(server, 5) == -1){LOG("listen error");return -1;}puts("Tcp server start success");int client = -1;struct sockaddr_in caddr = {0};socklen_t len = sizeof(caddr);pid_t pid = -1;while(1){//创建与客户端通信的套接字if((client = accept(server, (struct sockaddr*)&caddr, &len)) == -1){LOG("accpet error");return -1;}printf("[%s/%d] client已上线\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port));//创建子进程if((pid = fork()) < 0){LOG("fork error");return -1;}else if(pid == 0){cil(client, caddr);exit(0);}close(client);}close(server);return 0;
}void cil(int client, struct sockaddr_in caddr)
{char buf[128] = "";int res = 0;while(1){bzero(buf, sizeof(buf));if((res = read(client, buf, sizeof(buf))) < 0){LOG("read error");break;}else if(res == 0){printf("[%s/%d] client已下线\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port));close(client);break;}printf("[%s/%d] client: %s\n", inet_ntoa(caddr.sin_addr), ntohl(caddr.sin_port), buf);bzero(buf, sizeof(buf));strcpy(buf, "ok");if(write(client, buf, sizeof(buf)) < 0){LOG("write error");break;}}}

框架二(使用孤儿进程机制避免僵尸进程产生)

int main()
{//创建服务器监听套接字 serverserver = socket();//给服务器地址信息结构体赋值,并绑定bind();//监听指定端口,设置监听队列listen();while(1){//创建子进程if((pid = fork()) == 0){//子进程创建用于与客户端通信的clientclient = accept();//创建孙进程if(pid = fork() == 0){while(1){//孙进程负责与客户端通信recv();send();}//通信结束关闭套接字close(client);//退出进程exit(0);}//子进程else if(pid > 0){//关闭多余的文件描述符close(server);close(client);//退出子进程exit(0);}}//父进程else if(pid > 0){//回收子进程while(waitpid() == pid)}}//关闭文件描述符close(server);
}

实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>#define LOG(s) printf("[%s] {%s:%d} %s\n", __DATE__, __FILE__, __LINE__, s);void deal_cil_msg(int client, struct sockaddr_in caddr);int main(int argc, char *argv[])
{//创建服务器socketint server = 0;if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1){LOG("socket error");return -1;}//绑定服务器IP和端口号//给地址信息结构体赋值struct sockaddr_in saddr = {0};saddr.sin_family = AF_INET;saddr.sin_port = htons(8888);saddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1){LOG("bind error");return -1;}//监听对应的端口号if(listen(server, 5) == -1){LOG("listen error");return -1;}puts("server start success");//创建用于与客户端通信的socketstruct sockaddr_in caddr = {0};int client = 0;socklen_t asize = sizeof(caddr);pid_t pid = -1;int status = 0;while(1){//父进程只负责生儿子pid = fork();if(pid < 0){LOG("fork error");return -1;}//子进程负责创建通信socketif(pid == 0){//创建用于与客户端通信的socketif((client = accept(server, (struct sockaddr*)&caddr, &asize)) == -1){LOG("accept error");return -1;}printf("[%s/%d]client已上线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));//孙进程负责通信pid = fork();if(pid < 0){LOG("fork error");return -1;}else if(pid == 0){deal_cil_msg(client, caddr);close(client);exit(0);}else if(pid > 0){close(server);close(client);//退出子进程exit(0);}}else if(pid > 0){printf("wait child = %d\n", pid);//父进程等待子进程结束,准备收尸while(waitpid(pid, &status, 0) == pid){printf("Parent is over - child: %d, status = %x\n", pid, status);}}}//关闭文件描述符close(server);return 0;
}void deal_cil_msg(int client, struct sockaddr_in caddr)
{//接收消息char buf[128] = " ";while(1){int len = 0;bzero(buf, sizeof(buf));if((len = recv(client, buf, sizeof(buf), 0)) < 0){	LOG("recv error");}else if(len == 0){printf("[%s/%d]client已下线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));break;}printf("[%s/%d]client: %s\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), buf);bzero(buf, sizeof(buf));//发送消息strcpy(buf, "ok");write(client, buf, len);}}

多线程并发服务器

设计流程

//线程参数结构体
typedef struct
{int client;struct sockaddr_in caddr;
} Client_msg;int main()
{//创建服务器监听套接字 serverserver = socket();//给服务器地址信息结构体赋值,并绑定bind();//监听指定端口,设置监听队列listen();while(1){//创建用于与客户端通信的套接字client = accpet();//创建线程pthread_create();while(1){//读写//关闭文件描述符//退出线程}//解离线程pthread_detach();}//关闭文件描述符close(server);
}

实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <errno.h>#define LOG(s) printf("[%s] {%s:%d} %s \n", __DATE__, __FILE__, __LINE__, s);void* cil(void* arg);//线程参数结构体
typedef struct
{int client;struct sockaddr_in caddr;
} Cli_msg;int main(int argc, char *argv[])
{//创建服务器监听分套接字 serverint server = -1;if((server = socket(AF_INET, SOCK_STREAM, 0)) == -1){LOG("socket error");return -1;}//给服务器地址信息结构体赋值,并绑定struct sockaddr_in saddr = {0};saddr.sin_family = AF_INET;saddr.sin_port = htons(8899);saddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1){LOG("bind error");return -1;}//监听端口if(listen(server, 5) == -1){LOG("listen error");return -1;}puts("tcp server start success");struct sockaddr_in caddr = {0};socklen_t len = sizeof(caddr);pthread_t tid = -1;int client = -1;Cli_msg cli_msg;while(1){//创建用于与客户端通信的套接字 clientif((client = accept(server, (struct sockaddr*)&caddr, &len)) == -1){LOG("accept error");return -1;}printf("[%s/%d]client已上线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));cli_msg.client = client;cli_msg.caddr = caddr;//创建线程if(pthread_create(&tid, NULL, cil, &cli_msg) != 0){LOG("pthread_create error");return -1;}pthread_detach(tid);}close(server);return 0;
}void* cil(void* arg)
{int client = ((Cli_msg*)arg)->client;struct sockaddr_in caddr = ((Cli_msg*)arg)->caddr;char buf[128] = "";int res = 0;while(1){bzero(buf, sizeof(buf));if((res = read(client, buf, sizeof(buf))) < 0){LOG("read error");break;}else if(res == 0){printf("[%s/%d]client已下线\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));close(client);pthread_exit(NULL);}printf("[%s/%d]client: %s\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), buf);bzero(buf, sizeof(buf));strcpy(buf, "ok");if(write(client, buf, sizeof(buf)) < 0){LOG("write error");break;}}}

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

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

相关文章

Jenkins自动构建(Gitee)

Gitee简介安装JenkinsCLI https://blog.csdn.net/tongxin_tongmeng/article/details/132632743 安装Gitee jenkins-cli install-plugin gitee:1.2.7 # https://plugins.jenkins.io/gitee/releases获取安装命令(稍作变更) JenkinsURL Dashboard-->配置-->Jenkins Locatio…

ARTS第五周:A - 最大公约数

数字 function gcd(int $x, int $y): int {while($y^$x^$y^$x%$y);return $x; }位运算&#xff1a;异或&#xff1a;gcd(a,b) gcd(b,a mod b) 字符串 <?phpclass Solution {/*** param String $str1* param String $str2* return String*/function gcdOfStrings($str1, …

MySQL 8.0 OCP (1Z0-908) 考点精析-安装与配置考点1:设置系统变量

文章目录 MySQL 8.0 OCP (1Z0-908) 考点精析-安装与配置考点1&#xff1a;设置系统变量系统变量的确认设置系统变量的方法SET命令设置系统变量SET命令语法动态系统变量&#xff08;Dynamic System Variables&#xff09;全局级别变量的设置方法会话级别变量的设置方法系统变量的…

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?

如何使用好 ArkUI 的 Reusable&#xff1f; OpenHarmony 组件复用机制 在ArkUI中&#xff0c;UI显示的内容均为组件&#xff0c;由框架直接提供的称为 系统组件&#xff0c;由开发者定义的称为 自定义组件。 在进行 UI 界面开发时&#xff0c;通常不是简单的将系统组件进行组合…

SpringBoot的测试方案

写完代码后&#xff0c;测试是必不可少的步骤&#xff0c;现在来介绍一下基于SpringBoot的测试方法。 基于SpringBoot框架写完相应功能的Controller之后&#xff0c;然后就可以测试功能是否正常&#xff0c;本博客列举MockMvc和RestTemplate两种方式来测试。 准备代码 实体类…

NIO原理浅析(三)

epoll 首先认识一下epoll的几个基础函数 int s socket(AF_INET, SOCK_STREAM, 0); bind(s, ...); listen(s, ...);int epfd epoll_create(...) epoll_ctl(epfd, ...); //将所有需要监听的socket添加到epfd中while(1) {int n epoll_wait(...);for(接受到数据的socket) {//处…

Kotlin 环境下解决属性初始化问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

react使用hook封装一个tab组件

目录 react使用hook封装一个tab组件Tabbar.jsx使用组件效果 react使用hook封装一个tab组件 Tabbar.jsx import PropsTypes from "prop-types"; import React, { useEffect, useState } from react; export default function Tabbar(props) {const { tabData , cur…

使用pip下载第三方软件包报错超时处理方法

报错如下&#xff1a; WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by ‘ReadTimeoutEr ror(“HTTPSConnectionPool(host‘files.pythonhosted.org’, port443): Read timed out. (read timeout15)”)’: /p…

Spring Boot常用的参数验证技巧和使用方法

简介 Spring Boot是一个使用Java编写的开源框架&#xff0c;用于快速构建基于Spring的应用程序。在实际开发中&#xff0c;经常需要对输入参数进行验证&#xff0c;以确保数据的完整性和准确性。Spring Boot提供了多种方式来进行参数验证&#xff0c;并且可以很方便地集成到应…

Maven编译java及解决程序包org.apache.logging.log4j不存在问题

1、首先新建一个文件夹&#xff0c;比如hello Hello里新建pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

git快速使用

1、下载git 设置签名 2、基本概念 工作区&#xff1a;写代码的地方。 暂存区&#xff1a;.git的.index 工作区&#xff1a;.git 3、常用操作 本地codinggit init&#xff0c; 初始化一个本地仓库&#xff0c;项目根目录下会出现个.gitgit remote add origin gitgithub.com…

[杂谈]-快速了解LoRaWAN网络以及工作原理

快速了解LoRaWAN网络以及工作原理 文章目录 快速了解LoRaWAN网络以及工作原理1、LoRaWAN网络元素1.1 终端设备&#xff08;End Devices&#xff09;1.2 网关&#xff08;Gateways&#xff09;1.3 网络服务器&#xff08;Net Server&#xff09;1.4 应用服务器&#xff08;Appli…

Android11去掉Settings中的网络和互联网一级菜单

碰到一个不要wifi不要蓝牙的项目&#xff0c;客户要求去掉Settings中的网络和互联网一级菜单&#xff0c;因为硬件都不贴&#xff0c;所以软件对应也要去掉。 我们可以根据packages/apps/Settings/res/xml/top_level_settings.xml的布局文件找到TopLevelNetworkEntryPreferenc…

OpenCV(二十一):椒盐噪声和高斯噪声的产生

目录 1.图像噪声介绍 2.椒盐噪声的产生 3.高斯噪声的产生 1.图像噪声介绍 噪声介绍 图像噪声是指在图像中存在的不期望的、随机的像素值变化&#xff0c;这些变化来源于多种因素。噪声可能导致图像细节模糊、失真或难以分辨。 以下是几种常见的图像噪声类型&#xff1a; 1…

Unity中神秘的Transform和transform(小写)的关系

1.为什么Transform类是保护的不能通过new 来实例化对象,也没有静态函数,而Rotate()这种方法却属于它,该如何访问? Transform 类还是被保护的不允许用户修改! protected Transform(); 是一个受保护的构造函数,不能直接实例化 Transform 类。 2.为甚么transform可以访问Tr…

Mac Homebrew中常用的 Brew 命令

Mac 中常用的 Brew 命令集 Brew&#xff08;Homebrew&#xff09;是一个强大的包管理器&#xff0c;用于在 macOS 上安装、更新和管理各种软件包。它使得在 Mac 上安装开发工具、应用程序和库变得轻松和便捷。本博客将介绍一些在 Mac 中常用的 Brew 命令&#xff0c;以帮助您更…

C#设计打开文件

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System

【Springcloud】Sentinel熔断和降级

【Springcloud】Sentinel熔断和降级 【一】基本介绍【1】什么是熔断和降级【2】为什么使用熔断和降级【3】Sentinel熔断和降级【4】核心概念 【二】下载方式【1】Windows平台安装包下载【2】打开控制台 【三】使用案例【1】添加依赖【2】添加Sentinel配置【3】添加TestUserCont…

线上问诊:数仓开发(一)

系列文章目录 线上问诊&#xff1a;业务数据采集 线上问诊&#xff1a;数仓数据同步 线上问诊&#xff1a;数仓开发(一) 文章目录 系列文章目录前言一、Hive on yarn二、数仓开发1.ODS开发2.DIM开发3.DWD开发 总结 前言 上次我们已经将MYSQL的数据传送到了HDFS&#xff0c;但…