利用多进程和多线程实现服务器端 的并发处理和实现

利用多进程和多线程实现服务器端 的并发处理和实现

实验目的

熟练掌握服务器端并发处理的方法。

实验原理

1.服务端每连接上一个客户端,都会为其分配一个线程,从而提高一个服务端同时响
应多个客户端时的效率
2.pthread_create 是类 Unix 操作系统(Unix、Linux、Mac OS X 等)的创建线程的函数。它的功能是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。
pthread_create 的返回值 表示成功,返回 0;表示出错,返回表示-1。
int pthread_create(pthread_t *tidp,const pthread_attr_t attr,
(void
)(start_rtn)(void),void *arg);
第一个参数为指向线程标识符的指针
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。

实验内容

1.服务器

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



#define PORT 1028
#define LISTENQ 10
#define BUFFSIZE 1024
int num = 0;

int passiveTCP() {
	int fd = socket(AF_INET, SOCK_STREAM, 0); 
	struct sockaddr_in addr;
	addr.sin_family = AF_INET; 
	addr.sin_port = htons(PORT); 
	addr.sin_addr.s_addr = INADDR_ANY;
	bind(fd, (struct sockaddr*)&addr, sizeof(addr)); 
	listen(fd, LISTENQ);
	return fd; // 返回套接字
}
void *func(void *arg) { // 线程运行的函数
	char recv_buf[BUFFSIZE]; 
	int fd = (int)(arg);
	int t;
	int cnt = 0;
	char filename[100] = { 0 }; // 文件名
	//让主线程执行
	//memset(buf, 0, sizeof(buf));
	recv(fd, filename, sizeof(filename), 0); 
	printf("#%s\n", filename);
	//	sleep(1);
	printf("$>fd = %d\n", fd);
	num ++;
	FILE *fp = fopen(filename, "w");
	memset(recv_buf, 0, BUFFSIZE);
	//recv(fd, recv_buf, sizeof(recv_buf), 0);
	printf("%s\n", recv_buf);
	printf("=====%d======\n", fd);
	while( (t =recv(fd, recv_buf, sizeof(recv_buf), 0)) > 0){
		fwrite(recv_buf, sizeof(char), t, fp);
		cnt ++;
		printf("t == %d\n", t);
		printf("$(%s:%d):%s", filename, cnt, recv_buf);
		memset(recv_buf, 0, BUFFSIZE);
	}

	printf("$%d>%s-->OK!\n", fd, filename);
	fclose(fp);
	close(fd);
}

int main() {
	int serv_fd = passiveTCP(); 
	int clie_fd;

	struct sockaddr_in clie_addr; 
	socklen_t len = sizeof(clie_addr); 
	int pid;
	pthread_t pth; 
	while (1) {
		printf("等待连接\n");
		//char buf[1024];
		clie_fd = accept(serv_fd, (struct sockaddr *)&clie_addr, &len); 
		if( clie_fd > 0 ){
			printf("success\n");
		}
		else{
			printf("error\n");
			continue;
		}
		if (clie_fd == -1) {
			printf("error\n");
		}
		else {
			//num ++;
			//printf("#%d>%d\n", num, clie_fd);
			pid = pthread_create(&pth, NULL, func, (void *)(clie_fd));//创建线程
		}
	//	sleep(5); // 让子线程执行
	//	close(clie_fd);
	}
	close(serv_fd); 
	return 0;
}

2.客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 1028
#define IP "127.0.0.1" 
int main() {
	int fd = socket(AF_INET, SOCK_STREAM, 0); 
	struct sockaddr_in addr;

	char buf[1024] = { 0 };
	addr.sin_family = AF_INET; 
	addr.sin_port = htons(PORT);
	inet_pton(AF_INET, IP, &(addr.sin_addr.s_addr));
	if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) 
	{ 
		printf("error\n");
	}
	else {
		printf("success\n"); 
	}
	char filename[100] = { 0 };
	printf("input file name:");
	scanf("%s", filename);
	FILE *fp = fopen(filename, "r");
	while( fp == NULL){
		printf("file not exist");
		printf("input file name:");
		scanf("%s", filename);
		fp = fopen(filename, "r");
	}
	send(fd, filename, strlen(filename)*sizeof(char)+1, 0); 
	int n;
	sleep(3);
	fflush(stdout);
	// 读文件直到文件结尾
	/*
	while(!feof(fp)){ 
		fgets(buf, 1024, fp);
		printf("&>%s", buf);
		send(fd, buf, strlen(buf), 0);
		memset(buf, 0, sizeof(buf)); // 清零
	//	sleep(1);// 慢慢发,观察程序的并发
	}
	*/
	send(fd, filename, strlen(filename)*sizeof(char)+1, 0); 
	while( (n = fread(buf, sizeof(char), 1024, fp) )> 0){
		send(fd, buf, n, 0);
		memset(buf, 0, sizeof(buf)); // 清零
	}
	sleep(5);
	fclose(fp);
	close(fd);

	return 0;
}

多进程:

服务器端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#define PORT 1028
#define LISTENQ 10
#define BUFFSIZE 1024
int num = 0;
int passiveTCP() {
	int fd = socket(AF_INET, SOCK_STREAM, 0); 
	struct sockaddr_in addr;
	addr.sin_family = AF_INET; 
	addr.sin_port = htons(PORT); 
	addr.sin_addr.s_addr = INADDR_ANY;
	bind(fd, (struct sockaddr*)&addr, sizeof(addr)); 
	listen(fd, LISTENQ);
return fd; // 返回套接字
}
int main() {
	int serv_fd = passiveTCP(); 
	int clie_fd;
	struct sockaddr_in clie_addr; 
	socklen_t len = sizeof(clie_addr);	
	pid_t pid; 
	while (1) {
		printf("等待连接\n");

		//char buf[1024];
		clie_fd = accept(serv_fd, (struct sockaddr *)&clie_addr, &len); 
		if( clie_fd > 0 ){
	printf("success\n");
		}
		else{
			printf("error\n");
			continue;
		}
		if (clie_fd == -1) {
			printf("error\n");
		}
		else {
			//num ++;
			//printf("#%d>%d\n", num, clie_fd);
			pid = fork(); 
		}
		if( pid == 0 ){			
			char recv_buf[BUFFSIZE]; 
			int t;
			int cnt = 0;
			char filename[100] = { 0 }; // 文件名
			//memset(buf, 0, sizeof(buf));
			recv(clie_fd, filename, sizeof(filename), 0); 
			printf("#%s\n", filename);

			//	sleep(1);
			printf("$>fd = %d\n", clie_fd);
			num ++;
			FILE *fp = fopen(filename, "w");
			memset(recv_buf, 0, BUFFSIZE);
			//recv(fd, recv_buf, sizeof(recv_buf), 0);
			printf("%s\n", recv_buf);
			printf("=====%d======\n", clie_fd);
			while( (t =recv(clie_fd, recv_buf, sizeof(recv_buf), 0)) > 0){
				fwrite(recv_buf, sizeof(char), t, fp);
				cnt ++;
				printf("t == %d\n", t);
				printf("$(%s:%d):%s", filename, cnt, recv_buf);
				memset(recv_buf, 0, BUFFSIZE);
			}
			printf("$%d>%s-->OK!\n", clie_fd, filename);
			fclose(fp);
			close(clie_fd);
		}
		else if( pid > 0 ){
			close(clie_fd);
		}
	}

	close(serv_fd); 
	return 0;

}

实验结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Hello Spring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值