网络编程:服务器模型-并发服务器-多线程实现并发服务器

news2024/11/26 16:58:58

思想:

主进程专门用于连接多个客户端的请求,若有一条客户端连接进来,主进程就创建一个子进程,用该子进程来处理客户端的业务数据。

tcp_server.c 

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>//sockaddr_in
#include <unistd.h>
#include <arpa/inet.h>   // 包含 inet_addr 函数的声明 
#include <pthread.h>
#define BUF_SIZE 20

void *ThreadFunc(void *arg)
{
	int iClient = *(int *)arg;

	char buf[BUF_SIZE] = {0};

	int ret = -1;

	while(1){
		ret = recv(iClient, buf, BUF_SIZE, 0);
		if(ret <= 0){
			printf("recv error!\r\n");
			close(iClient);
			pthread_exit("thread exit");
		}
		printf("server recv data:%s\r\n",buf);
		//send
		send(iClient, buf, BUF_SIZE, 0);
	}
}

int main(int argc, const char *argv[])
{
	//1.socket
	int iServer = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == iServer){
		puts("----------1、create socket error!----------");
		return -1;
	}
	puts("----------1、create socket ok!----------");

	//2.bind
	struct sockaddr_in stServer;
	stServer.sin_family = AF_INET;//第一个成员
	stServer.sin_port = htons(8888);//第二个成员
	stServer.sin_addr.s_addr = inet_addr("127.0.0.1");//将点分十进制ip地址转换为32位无符号整数
	int ret = bind(iServer, (struct sockaddr *)&stServer, sizeof(struct sockaddr));
	if(-1 == ret){
		puts("----------2、bind error!----------");
		return -1;
	}
	puts("----------2、bind ok!----------");
	
	//3.listen
	ret = listen(iServer, 5);
	if(-1 == ret){
		puts("----------3、listen error!----------");
		return -1;
	}
	puts("----------3、listen ok!----------");

	//4.accept
		//函数原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
		//函数作用:接收客户端的连接请求
		//参数1:文件描述符 ---> socket的返回值
		//参数2:指向存放对方主机信息结构体的指针
		//参数3:指向struct sockaddr大小的指针
		//返回值:成功返回 新的文件描述符 ---> 标识一个新的网络软通道 --->
		//用做收发正文数据(recv/send), 失败 -1
	struct sockaddr_in stClient;//存放对方的主机信息
	socklen_t len = sizeof(struct sockaddr_in);
	char buf[BUF_SIZE] = {0};
	while(1){
		memset(buf, 0, BUF_SIZE);
		int iClient = accept(iServer, (struct sockaddr *)&stClient, &len);
		if(-1 == iClient){
			continue;//当前客户端出错转向下一个客户端	
		}
		printf("----------4、accept ok! iClient = %d\r\n----------",iClient );//标准输入输出出错,所以下一个打开的文件一定是4
		// \r\n适用于所有操作系统,此考虑系统移植
		
		//thread
		pthread_t tID = -1;
		if(0 != pthread_create(&tID, NULL, ThreadFunc, &iClient)){
			perror("create thread error");
			close(iClient);
			continue;
		}
		printf("create thread ok! iClient:%d\r\n",iClient);
	}

	
	return 0;
}

tcp_client.c 

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




#define BUF_SIZE 20
//main函数参数,如果需要键入IP则给定即可
int main(int argc, const char *argv[])
{
	//1、socket
	int iClient = 	socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == iClient){
		puts("----------1、create socket error!");
		return -1;
	}
	puts("----------1、create socket ok!");

	//2、connect
	struct sockaddr_in stServer;
	stServer.sin_family = AF_INET;
	stServer.sin_port = htons(8888);
	//stServer.sin_addr.s_addr = inet_addr("192.168.15.71");
	stServer.sin_addr.s_addr = inet_addr("127.0.0.1");
	int ret = connect(iClient, (struct sockaddr *)&stServer, sizeof(struct sockaddr_in));
	if(-1 == ret){
		puts("----------2、connect error!");
		return -1;
	}
	puts("----------2、connect ok!");

	char buf[BUF_SIZE] = {0};
	while(1){
		//gets();
		//char *fgets(char *s, int size, FILE *stream);
		fgets(buf, BUF_SIZE, stdin);//更安全,边界检查

		//3、send recv
		ret = send(iClient, buf, BUF_SIZE, 0);
		if(-1 == ret){
			puts("----------3、send data error!");
		}
		printf("----------3、send data ok! buf = %s\r\n",buf);

		//recv
		//函数原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
		memset(buf, 0, BUF_SIZE);
		ret = recv(iClient, buf, BUF_SIZE, 0);
		if(-1 == ret){
			puts("----------4、recv error!");
			return -1;
		}
		printf("----------4、recv data ok! buf = %s\r\n",buf);
	}
	//close(iClient);

	return 0;
}

运行效果图如下👇

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

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

相关文章

YOLOv8小白中的小白安装环境教程!没一个字废话,看一遍不踩坑!

文章目录 去哪里下代码&#xff1f;怎么下代码&#xff1f;怎么装环境&#xff1f;命令行界面(CLI)指令和Python脚本区别&#xff1f;附录1 conda常用指令附录2 git常用指令附录3 项目代码文件作用 去哪里下代码&#xff1f; 下载代码请大家直接去 YOLOv8的官方仓库下载&#…

内存屏障 - LINUX KERNEL MEMORY BARRIERS 上 与 下

内存屏障&#xff08;Memory Barrier&#xff09;是在计算机体系结构中使用的一种同步机制&#xff0c;用于确保在多线程或多核处理器环境中&#xff0c;对共享内存的操作按照预期顺序进行。它们通过强制在特定点执行一些指令来规定内存访问的顺序&#xff0c;并防止内存乱序执…

MySQL的msi格式安装

一、下载链接 MySQL :: Download MySQL Installer (Archived Versions) 二、安装步骤 ①选择自定义安装 ②选择要安装的产品 ③安装依赖环境 ④安装 ⑤点击下一步 ⑥配置 ⑦设置密码 ⑧命名 ⑨数据存放路径 ⑩安装配置 ①①配置环境变量 ①②验证 方法一&#xff1a; 方法二…

触摸OpenNJet,云原生世界触手可及

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 导言OpenNJet云原生引擎介绍云原生平台的介绍优化与创新 为什么选择OpenNJet云原生引擎如何在windo…

探索未知:风靡硅谷开发者的 Unstructured Data Meetup 即将登陆中国

“最硅谷”的 Unstructured Data Meetup 即将来袭&#xff01; 众所周知&#xff0c;AI 三要素包括&#xff1a;算力、算法和数据。数据的价值愈发凸显&#xff0c;而其中非结构化数据更是备受关注。IDC 预测&#xff0c;到 2025 年&#xff0c;全球数据总量中将有超过 80% 的数…

Unreal Engine插件打包技巧

打开UE工程&#xff0c;点击编辑&#xff0c;选择插件&#xff0c;点击"打包"按钮&#xff0c;选择输出目录UE4.26版本打包提示需要VS2017问题解决 1&#xff09;用记事本打开文件【UE4对应版本安装目录\Epic Games\UE_4.26\Engine\Build\BatchFiles\RunUAT.bat】 2&…

cookie、session、token、表单、json、jsonp、websocket、ajax都是什么

前后端数据交互的几种方式 1.cookie Cookie是服务器保存在客户端的一小段数据&#xff0c;&#xff08;使用Cookie的前提是客户端浏览器允许使用Cookie并对此做出相应的设置。&#xff09; cookie是一种存储在用户计算机上的小型数据文件&#xff0c;常用于在web应用程序中跟…

【计算机网络】数据链路层 组帧 习题4

组帧 发送方根据一定的规则将网络层递交的分组封装成帧(也称为组帧)。 组帧时&#xff0c;既要加首部&#xff0c;也要加尾部&#xff0c;原因是&#xff0c;在网络信息中&#xff0c;帧是以最小单位传输的。所以接收方要正确地接收帧&#xff0c;就必须清楚该帧在一串比特串中…

Python如何绘制直流电机开闭环特性曲线?matplotlib

import matplotlib.pyplot as plt from pylab import mplmpl.rcParams[font.sans-serif] [FangSong] # 指定默认字体 mpl.rcParams[axes.unicode_minus] False # 解决保存图像是负号-显示为方块的问题# 数据集1 n1 [1206, 1174, 1141, 1116, 1037, 986] Id1 [0.505, 0.55…

实训一:设计系统主页作业

1.题目 设计系统主页。 2.目的 (1)熟悉Web前端项目开发环境。 (2)掌握如何建立Web前端项目&#xff0c;学会规划项目结构。 (3)掌握动态生成页面内容的方法。 (4)理解如何使用Flash显示图片新闻。 (5)会在应用系统中编写播放动态新闻的程序。 3.内容 建立项目结构&#xff0c;并…

户外无比精彩 ,体育无处不在!CISP深圳国际体育展官宣2025年重磅来袭

CISP深圳国际体育展【 同期举办&#xff1a;COSP深圳国际户外展 】 时间&#xff1a;2025年2月27-3月1日 地点&#xff1a;深圳&#xff08;福田会展中心&#xff09; 主办单位&#xff1a;东莞市体育产业协会 协办单位&#xff1a;中国户外探险联盟 深圳市登山户外运动协…

无人机+通信中继:短波电台技术详解

随着无线通信技术的不断发展&#xff0c;无人机作为一种新型的信息传输平台&#xff0c;已经在多个领域得到了广泛应用。其中&#xff0c;无人机与短波电台的结合&#xff0c;为通信中继领域带来了全新的可能性。本文将详细解析无人机在通信中继中的应用&#xff0c;以及短波电…

ASP.NET医药进销存系统

摘 要 目前&#xff0c;大中型城市的多数药品店已经实现了商品管理、客户管理、销售管理及销售管理等的信息化和网络化&#xff0c;提高了管理效率。但是&#xff0c;在大多数小药品店&#xff0c;药品店管理仍然以传统人工管理为主&#xff0c;特别是在药品的采购、销售、库…

Q1咖啡机行业线上市场(京东天猫淘宝)销售数据分析

回顾疫情那几年&#xff0c;咖啡机市场可能是大环境带动下爆发飞速的品类之一。在整体厨房小家电大盘销售不佳的情况下&#xff0c; 咖啡机市场的表现是亮眼的。而今年Q1季度&#xff0c;在厨卫小电市场整体低迷的状态下&#xff0c;咖啡机市场依然保持着稳中向好的趋势。 根据…

哈希重要思想——位图详解

一&#xff0c;概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xff0c;数据无重复的场景。通常是用来判断某个数据存不存在的。 为了方便理解我们引入一道面试题&#xff0c; 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无…

形位公差Overview of GDT

零件公差产生于十九世纪后期&#xff0c;其初衷是为了保证零件的互换性。起初只有尺寸公差。由于 当时的设计部门和制造部门通常都在一起或就在隔壁&#xff0c;因此交流起来非常方便。在当时&#xff0c;给 定的公差一般都很大&#xff0c;因此当时的设备刀具的能力对于保证产…

【C++要哮着学】初识C++,什么是C++?什么是命名空间?什么又是缺省函数?

文章目录 前言1、C简介1.1、什么是C1.2、C起源1.3、C发展 2、C关键字&#xff08;C98&#xff09;3、命名空间3.1、命名空间的定义及使用3.2、命名空间的嵌套3.3、命名空间的三种使用方式3.3.1、加命名空间名称及作用域限定符3.3.2、使用using将命名空间中某个成员引入3.3.3、使…

【MySQL的内外连接】

文章目录 一、内连接二、外连接1.左外连接2.右外连接 一、内连接 基本语法&#xff1a; select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件&#xff1b;&#xff08;这里的and&#xff0c;也可以修改成where&#xff0c;并且建议使用where&#xff0c;逻辑更清晰…

何为LCA(最近共同祖先)?

原篇&#xff1a;&#xff08;ACM算法&#xff09;tarjan算法求LCA - 知乎 (zhihu.com) 顾名思义&#xff0c;就是求两个节点最近的共同祖先&#xff0c;就好比下图&#xff0c;2和3的共同祖先为3&#xff0c;2和4的共同祖先为1。 关于LCA求解有3种算法。 1.标记回溯法&#…

2024期从、证从、基从、银从备考资料及互助交流群

快进&#xff0c;2024年 金融考证备考资料及互助交流备考群&#xff0c;考啥进啥 5.12 &#xff08;基从&#xff09;基金从业资格考试 5.18&#xff08;期从&#xff09;期货从业资格考试 6.1 &#xff08;证从&#xff09;证券从业资格考试 6.1&#xff5e;6.2&#xff08;银…