Linux 基本语句_15_Tcp并发服务器

原理:

利用父子进程。父进程接收客户端的连接请求,子进程处理客户端的数据处理操作,两者各施其职。最终实现能够多个客户端连接一个服务端的操作。

代码:

服务端代码:

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

#define N 128

void handler(int sig){
   
	wait(NULL); // 不关心子进程状态,等待子进程终止,回收其资源 
}

int main(int argc, const char *argv[]){
   
	
	int sockfd, acceptfd;
	
	struct sockaddr_in severaddr, clientaddr; // 存储客户端和服务器的地址信息 
	socklen_t addrlen = sizeof(severaddr);
	char buf[N] = "";
	pid_t pid;
	
	bzero(&severaddr, addrlen);  
	bzero(&clientaddr, addrlen); // 清除特定长度的区域 
	
	if(argc < 3){
   
		printf("argc number error\n");
		return -1;
	}
	
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    // IPv4协议、流式套接字 (创建套接字) 
		printf("socket create error\n");
		return -1;
	}
	
	/* 填充信息 */
	
	severaddr.sin_family = AF_INET;
	severaddr.sin_addr.s_addr = inet_addr(argv[1]);
	severaddr.sin_port = htons(atoi(argv[2]));
	
	/* 将套接字与服务器网络信息结构体绑定 */
	
	if(bind(sockfd, (struct sockaddr *) &severaddr, addrlen) < 0){
   
		printf("bind error\n");
		return -1;
	}
	
	if(listen(sockfd, 5) < 0){
    // 设置被动监听模式 
		printf("listen error\n");
		return -1; 
	}
	
	signal(SIGUSR1, handler); // 注册一个信号 
	
	while(1){
    // 等待客户端连接请求 
		if((acceptfd = accept(sockfd, (struct sockaddr *) &clientaddr, &addrlen)) < 0){
    // 阻塞等待 
			printf("accept error\n");
		}
		
		printf("ip : %s, port : %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
		
		pid = fork(); // 创建子进程 
		
		if(pid < 0){
   
			printf("fork error\n");
			return -1;
		}
		else if(pid == 0){
    // 子进程 
			close(sockfd); // 只需要处理信息,不负责客户端连接
			
			while(1){
   
				ssize_t bytes;
				if((bytes = recv(acceptfd, buf, N, 0)) < 0){
   
					printf("recv error\n");
					return -1;
				}
				else if(bytes == 0){
   
					printf("no data\n");
				}
				else{
   
					if(strncmp(buf, "quit", 4) == 0){
   
						printf("client quit\n");
						sleep(1);
						break;
					}
					else{
   
						printf("client: %s\n", buf);
						strcat(buf, "-server");
						
						if(send(acceptfd, buf, N, 0) < 0){
   
							printf("send error\n");
							return -1;
						}
					}
				}
			}
			kill(getppid(), SIGUSR1);
			exit(0); 
		}
		else{
   
			close(acceptfd); // 释放资源,关闭与客户端连接 
		} 
	}
	return 0; 
}

客户端代码:

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

#define N 128

void handler(int sig){
   
	wait(NULL); // 不关心子进程状态,等待子进程终止,回收其资源 
}

int main(int argc, const char *argv[]){
   
	
	int sockfd, acceptfd;
	
	struct sockaddr_in serveraddr, clientaddr; // 存储客户端和服务器的地址信息 
	socklen_t addrlen = sizeof(serveraddr);
	char buf[N] = "";
	pid_t pid;
	
	bzero(&serveraddr, addrlen);  
	bzero(&clientaddr, addrlen); // 清除特定长度的区域 
	
	if(argc < 3){
   
		printf("argc number error\n");
		return -1;
	}
	
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    // IPv4协议、流式套接字 (创建套接字) 
		printf("socket create error\n");
		return -1;
	}
	
	/* 填充信息 */
	
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
	serveraddr.sin_port = htons(atoi(argv[2]));
	
	/* 将套接字与服务器网络信息结构体绑定 */
	
/*	if(bind(sockfd, (struct sockaddr *) &severaddr, addrlen) < 0){
		printf("bind error\n");
		return -1;
	}
	
	if(listen(sockfd, 5) < 0){ // 设置被动监听模式 
		printf("listen error\n");
		return -1; 
	}

	
	signal(SIGUSR1, handler); // 注册一个信号 
*/
    if(connect(sockfd, (struct sockaddr *) &serveraddr, addrlen) < 0){
    // 发送客户端连接请求 
    	printf("connect error\n");
    	return -1;
	}
	
	while(1){
    // 等待客户端连接请求 
        fgets(buf, N, stdin);
		buf[strlen(buf) - 1] = '\0';
		
		if(send(sockfd, buf, N, 0) < 0){
   
			printf("send error\n");
			return -1;
		}
		else{
   
			if(strncmp(buf, "quit", 4) == 0){
   
				break;
			}
		}
		if(recv(sockfd, buf, N, 0) < 0){
   
			printf("recv error\n");
			return -1;
		}
		printf("server: %s\n", buf); 
	}
	return 0; 
}

效果:

在这里插入图片描述

相关推荐

  1. Linux基于tcp的简单服务器程序

    2023-12-17 08:46:04       12 阅读
  2. C语言基于TCP的多线程服务器

    2023-12-17 08:46:04       19 阅读
  3. Linux下网络编程-基于多任务的简易并发服务器

    2023-12-17 08:46:04       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-17 08:46:04       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-17 08:46:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-17 08:46:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-17 08:46:04       20 阅读

热门阅读

  1. Ansible运行临时命令

    2023-12-17 08:46:04       41 阅读
  2. Ansible设置主机清单

    2023-12-17 08:46:04       37 阅读
  3. 加州数据集介绍

    2023-12-17 08:46:04       37 阅读
  4. 安卓免Root做klipper上位机教程

    2023-12-17 08:46:04       57 阅读
  5. 如何进行软件测试和测试驱动开发(TDD)?

    2023-12-17 08:46:04       35 阅读
  6. CentOS新系统工具安装

    2023-12-17 08:46:04       51 阅读
  7. 如何下载 GitHub 私有仓库

    2023-12-17 08:46:04       34 阅读