多进程/线程并发服务器

多进程:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define SER_PORT 8888
#define SER_IP  "192.168.124.242"   //"0.0.0.0"

int deal_cli_msg( int newfd, struct sockaddr_in cin);

int main(int argc, const char *argv[])
{
	//创建流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("socket");
		return -1;
	}
	printf("socket success __%d__\n", __LINE__);


	//允许端口快速重用                                                                                  
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("setsockopt");
		return -1;
	}
	printf("reuseaddr success __%d__\n", __LINE__);

	//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号
	int port =  argc>=2?atoi(argv[1]):SER_PORT;

	//填充服务器的地址信息结构体,给bind函数使用
	//真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip
	struct sockaddr_in sin;
	sin.sin_family      = AF_INET;              //必须填AF_INET
	sin.sin_port        = htons(port);          //端口号的网络字节序,1024~49151
	sin.sin_addr.s_addr = inet_addr(SER_IP);    //本机IP的网络字节序,ifconfig查看本机IP
	//127.0.0.1:本地换回IP,只能做本机通信的IP
	//0.0.0.0 : 代表运行环境中所有可用IP

	//绑定服务器自身的地址信息
	if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("bind");
		return -1;
	}
	printf("bind success __%d__\n", __LINE__);


	//将套接字设置为被动监听状态
	if(listen(sfd, 128) < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("listen");
		return -1;
	}
	printf("listen success __%d__\n", __LINE__);

	//阻塞等待客户端连接成功,从已完成连接的队列头中获取一个客户端信息,
	//生成一个新的文件描述符,这个新的文件描述符才是与客户端通信用的文件描述符
	struct sockaddr_in cin;     //存储获取到的客户端的地址信息
	socklen_t addrlen = sizeof(cin);

	int newfd = -1;
	pid_t pid = 0;

	while(1)
	{
		//父进程负责处理客户端连接事件
		newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);
		if(newfd < 0)
		{
			fprintf(stderr, "__%d__ ", __LINE__);
			perror("accpet");
			return -1;
		}
		printf("client connect success, [%s:%d] newfd = %d __%d__\n", \
				inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);

		//有客户端连接成功,需要创建子进程负责与客户端通信
		pid = fork();
		if( 0 == pid)
		{
			close(sfd);//子进程中的sfd
			deal_cli_msg(newfd, cin);
			break;        //or exit(0);子进程只负责与客户端交互,客户端退出,子进程需要结束
		}
		close(newfd);//父进程的newfd;
	}
	close(sfd);//父进程中的sfd

	return 0;
}


int deal_cli_msg( int newfd, struct sockaddr_in cin)
{
	char buf[128] = "";
	ssize_t res = 0;
	while(1)
	{
		bzero(buf, sizeof(buf));    //memset(buf, 0, sizeof(buf));
		//收
		res = recv(newfd, buf, sizeof(buf), 0);
		if(res < 0)
		{
			fprintf(stderr, "__%d__ ", __LINE__);
			perror("recv");
			return -1;
		}
		else if(0 == res)
		{
			printf("client [%s:%d] offline  __%d__\n",\
					inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), __LINE__);
			break;
		}

		printf("[%s:%d] newfd=%d : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, buf);

		//发
		strcat(buf, "*_*");
		if(send(newfd, buf, sizeof(buf), 0) < 0)
		{
			fprintf(stderr, "__%d__ ", __LINE__);
			perror("send");
			return -1;
		}
		printf("send success __%d__\n", __LINE__);
	}
	close(newfd);//子进程中的newfd
	return 0;
}

多线程:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define SER_PORT 8888
#define SER_IP  "192.168.124.242"   //"0.0.0.0"

int deal_cli_msg( int newfd, struct sockaddr_in cin);

int main(int argc, const char *argv[])
{
	//创建流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sfd < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("socket");
		return -1;
	}
	printf("socket success __%d__\n", __LINE__);
	//允许端口快速重用                                                                                  
	int reuse = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("setsockopt");
		return -1;
	}
	printf("reuseaddr success __%d__\n", __LINE__);

	//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号
	int port =  argc>=2?atoi(argv[1]):SER_PORT;

	//填充服务器的地址信息结构体,给bind函数使用
	//真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip
	struct sockaddr_in sin;
	sin.sin_family      = AF_INET;              //必须填AF_INET
	sin.sin_port        = htons(port);          //端口号的网络字节序,1024~49151
	sin.sin_addr.s_addr = inet_addr(SER_IP);    //本机IP的网络字节序,ifconfig查看本机IP
	//127.0.0.1:本地换回IP,只能做本机通信的IP
	//0.0.0.0 : 代表运行环境中所有可用IP

	//绑定服务器自身的地址信息
	if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("bind");
		return -1;
	}
	printf("bind success __%d__\n", __LINE__);


	//将套接字设置为被动监听状态
	if(listen(sfd, 128) < 0)
	{
		fprintf(stderr, "__%d__ ", __LINE__);
		perror("listen");
		return -1;
	}
	printf("listen success __%d__\n", __LINE__);

	//阻塞等待客户端连接成功,从已完成连接的队列头中获取一个客户端信息,
	//生成一个新的文件描述符,这个新的文件描述符才是与客户端通信用的文件描述符
	struct sockaddr_in cin;     //存储获取到的客户端的地址信息
	socklen_t addrlen = sizeof(cin);

	int newfd;
	pthread_t tid;
	struct Climsg pcli;

	while(1)
	{
		//主线程负责处理客户端连接事件
		newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);
		if(newfd < 0)
		{
			fprintf(stderr, "__%d__ ", __LINE__);
			perror("accpet");
			return -1;
		}
		printf("client connect success, [%s:%d] newfd = %d __%d__\n", \
				inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);

		//有客户端连接成功,需要创建一个子线程负责与客户端通信
		
		pthread_create( &tid, NULL, deal_cli_msg, (void*)&pcli);
		pthread_detach( tid);
	}
	close(sfd);//父进程中的sfd

	return 0;
}

//线程回调函数
void* deal_cli_msg( void* arg )
{
	int newfd = ( (struct Climsg*)arg )->newfd;
	struct sockaddr_in cin = ( (struct Climsg*)arg)->cin;
	
	char buf[128] = "";
	ssize_t res = 0;
	while(1)
	{
		bzero(buf, sizeof(buf));    //memset(buf, 0, sizeof(buf));
		//收
		res = recv(newfd, buf, sizeof(buf), 0);
		if(res < 0)
		{
			fprintf(stderr, "__%d__ ", __LINE__);
			perror("recv");
			return -1;
		}
		else if(0 == res)
		{
			printf("client [%s:%d] offline  __%d__\n",\
					inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), __LINE__);
			break;
		}

		printf("[%s:%d] newfd=%d : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, buf);

		//发
		strcat(buf, "*_*");
		if(send(newfd, buf, sizeof(buf), 0) < 0)
		{
			fprintf(stderr, "__%d__ ", __LINE__);
			perror("send");
			return -1;
		}
		printf("send success __%d__\n", __LINE__);
	}
	close(newfd);//子线程中的newfd
	
	pthread_exit( NULL);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【前端】深入浅出 - TypeScript 的详细讲解

TypeScript 是一种静态类型编程语言&#xff0c;它是 JavaScript 的超集&#xff0c;添加了类型系统和编译时检查。TypeScript 的主要目标是提高大型项目的开发效率和可维护性。本文将详细介绍 TypeScript 的核心概念、语法、类型系统、高级特性以及最佳实践。 1. TypeScript…

查询DBA_FREE_SPACE缓慢问题

这个是一个常见的问题&#xff0c;理论上应该也算是一个bug&#xff0c;在oracle10g&#xff0c;到19c&#xff0c;我都曾经遇到过&#xff1b;今天在给两套新建的19C RAC添加监控脚本时&#xff0c;又发现了这个问题&#xff0c;在这里记录一下。 Symptoms 环境&#xff1a;…

The Internals of PostgreSQL 翻译版 持续更新...

为了方便自己快速学习&#xff0c;整理了翻译版本&#xff0c;目前翻译的还不完善&#xff0c;后续会边学习边完善。 文档用于自己快速参考&#xff0c;会持续修正&#xff0c;能力有限,无法确保正确!!! 《The Internals of PostgreSQL 》 不是 《 PostgreSQL14 Internals 》…

机器学习 ---模型评估、选择与验证(1)

目录 前言 一、为什么要有训练集与测试集 1、为什么要有训练集与测试集 2、如何划分训练集与测试集 二、欠拟合与过拟合 1、什么是欠拟合与欠拟合的原因 2、什么是过拟合与过拟合的原因 一些解决模型过拟合和欠拟合问题的常见方法&#xff1a; 解决过拟合问题&#…

一文简单了解Android中的input流程

在 Android 中&#xff0c;输入事件&#xff08;例如触摸、按键&#xff09;从硬件传递到应用程序并最终由应用层消费。整个过程涉及多个系统层次&#xff0c;包括硬件层、Linux 内核、Native 层、Framework 层和应用层。我们将深入解析这一流程&#xff0c;并结合代码逐步了解…

【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题

目录 1. 单例模式 (1) 饿汉模式 (2) 懒汉模式 1. 单线程版本 2. 多线程版本 2. 解决懒汉模式产生的线程安全问题 (1) 产生线程安全的原因 (2) 解决线程安全问题 1. 通过加锁让读写操作紧密执行 方法一 方法二 2. 处理加锁引入的新问题 问题描述 …

二叉树搜索树(下)

二叉树搜索树&#xff08;下&#xff09; 二叉搜索树key和key/value使用场景 key搜索场景 只有key作为关键码&#xff0c;结构中只需要存储key即可&#xff0c;关键码即为需要搜索到的值&#xff0c;搜索场景只需要判断 key在不在。key的搜索场景实现的二叉树搜索树支持增删查…

Web项目版本更新及时通知

背景 单页应用&#xff0c;项目更新时&#xff0c;部分用户会出更新不及时&#xff0c;导致异常的问题。 技术方案 给出版本号&#xff0c;项目每次更新时通知用户&#xff0c;版本已经更新需要刷新页面。 版本号更新方案版本号变更后通知用户哪些用户需要通知&#xff1f;…

D64【python 接口自动化学习】- python基础之数据库

day64 SQL-DQL-基础查询 学习日期&#xff1a;20241110 学习目标&#xff1a;MySQL数据库-- 133 SQL-DQL-基础查询 学习笔记&#xff1a; 基础数据查询 基础数据查询-过滤 总结 基础查询的语法&#xff1a;select 字段列表|* from 表过滤查询的语法&#xff1a;select 字段…

Unity插件-Smart Inspector 免费的,接近虚幻引擎的蓝图Tab管理

习惯了虚幻的一张蓝图&#xff0c;关联所有Tab &#xff08;才发现Unity&#xff0c;的Component一直被人吐槽&#xff0c;但实际上是&#xff1a;本身结构Unity 的GameObject-Comp结构&#xff0c;是好的不能再好了&#xff0c;只是配上 smart Inspector就更清晰了&#xff0…

2024 年Postman 如何安装汉化中文版?

2024 年 Postman 的汉化中文版安装教程

单元测试、集成测试、系统测试、验收测试、压力测试、性能测试、安全性测试、兼容性测试、回归测试(超详细的分类介绍及教学)

目录 1.单元测试 实现单元测试的方法&#xff1a; 注意事项&#xff1a; 2.集成测试 需注意事项&#xff1a; 实现集成测试的方法&#xff1a; 如何实现高效且可靠的集成测试&#xff1a; 3.系统测试 实现系统测试的方法: 须知注意事项&#xff1a; 4.验收测试 实现验…

MySQL 忘记 root 密码,使用跳过密码验证进行登录

操作系统版本&#xff1a;CentOS 7 MySQL 忘记 root 密码&#xff0c;使用跳过密码验证进行登录 修改 /etc/my.cnf 配置文件&#xff0c;在 [mysqld] 后面任意一行添加 skip-grant-tables vim /etc/my.cnf 重启 MySQL systemctl restart mysqld 登录 MySQL&#xff08;无 -…

3D Web渲染引擎HOOPS Communicator:助力企业打造定制化3D可视化产品的强大工具

HOOPS Communicator为开发人员提供了多样化的定制手段&#xff0c;使其在3D网页可视化领域保持领先地位。很多潜在客户都关心如何利用HOOPS Communicator将其打造成自己产品的独特解决方案。展示我们现有合作伙伴的成功案例正是分享此信息的最佳方式。 每家合作伙伴都在产品中…

【stablediffusion】阿里发布新ID保持项目EcomID, 可从单个ID参考图像生成定制的保ID图像,ComfyUI可使用。

今天&#xff0c;我们将向您介绍一款令人兴奋的更新——阿里发布的ID保持项目EcomID。这是一款基于Stable Diffusion技术的AI绘画工具&#xff0c;旨在为您提供一键式生成高质量保ID图像的便捷体验。无论您是AI绘画的新手还是专业人士&#xff0c;这个工具都能为您带来极大的便…

计算机网络(11)和流量控制补充

这一篇对数据链路层中的和流量控制进行详细学习 流量控制&#xff08;Flow Control&#xff09;是计算机网络中确保数据流平稳传输的技术&#xff0c;旨在防止数据发送方发送过多数据&#xff0c;导致接收方的缓冲区溢出&#xff0c;进而造成数据丢失或传输失败。流量控制通常…

【VLANPWN】一款针对VLAN的安全研究和渗透测试工具

关于VLANPWN VLANPWN是一款针对VLAN的安全研究和渗透测试工具&#xff0c;该工具可以帮助广大研究人员通过对VLAN执行渗透测试&#xff0c;来研究和分析目标VLAN的安全状况。该工具专为红队研究人员和安全学习爱好者设计&#xff0c;旨在训练网络工程师提升网络的安全性能&…

ES6代理和反射新特性,详细讲解

代理与反射 es6新增了代理和反射特性&#xff0c;这两个特性为开发者提供了拦截并向基本操作嵌入额外行为的能力。 代理基础 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta charset"UTF-8"&g…

MYSQL 精通索引【快速理解】

目录 1、什么是索引&#xff1f; 2、索引结构 1.为什么不使用二叉树呢&#xff1f; 2.B树数据结果 3.B树 4.Hash结构 3、索引语法 1.创建索引 2.查看索引 3.删除索引 4、SQL性能分析 1.SQL执行频次 2.慢查询日志 3.profile详情 4.EXPLAIN 5、索引规则 1.最左前缀法则 2.索…

光驱验证 MD5 校验和

步骤 1&#xff1a;在 Ubuntu 上打包文件并生成 MD5 校验和 打包文件 使用 tar 命令将文件夹打包成 tar.gz 文件&#xff1a; tar -czvf my_files.tar.gz /path/to/folder 生成 MD5 校验和 使用 md5sum 命令生成打包文件的 MD5 校验和&#xff1a; md5sum my_files.tar.g…