实现TCP并发服务器之一(多进程)

下面用多进程方式实现一个TCP并发服务器,每当一个新的客户端连接时fork一个子进程去和它通信。(各种主流的web服务器都不是纯粹的多进程方式运行,比如apache在每个进程中都用多路复用方式,直到连接数多到超过select可监听的最大描述符数时也会利用新的进程去处理。)

服务器端(server.c)

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


#define MAX_LISTEN 5
#define PORT 1987
#define IP "127.0.0.1"

void serve_proc(int conn_fd)
{
	int recv_num;
	int send_num;
	char recv_buf[100];
	char send_buf[100];	

	int pid = getpid();

	printf("client %d started\n", pid);

	while (1) {
		//receive
		recv_num = recv(conn_fd, recv_buf, sizeof(recv_buf), 0);
		if (recv_num < 0) {
			close(conn_fd);
			exit(1);
		}
		recv_buf[recv_num] = '\0';
		printf("child proc %d got : %s\n", pid, recv_buf);

		if (strcmp(recv_buf,"quit") == 0) {
			printf("child proc %d quit\n", pid);
			break;
		}

		//send
		sprintf(send_buf, "server proc got %d bytes\n", recv_num);
		send_num = send(conn_fd, send_buf, strlen(send_buf), 0);
		if (send_num < 0) {
			close(conn_fd);
			exit(1);
		}
		printf("child proc %d sent : %s\n", pid, send_buf);
	}

	close(conn_fd);
}

int main()
{
	pid_t pid;

	int conn_fd;
	int sock_fd = socket(AF_INET,SOCK_STREAM,0);
	if (sock_fd < 0) {
		perror("create socket failed");
		exit(1);
	}

	struct sockaddr_in addr_client;
	int client_size = sizeof(struct sockaddr_in);

	struct sockaddr_in addr_serv;
	memset(&addr_serv, 0, sizeof(addr_serv));
	addr_serv.sin_family = AF_INET;
	addr_serv.sin_port = htons(PORT);
	addr_serv.sin_addr.s_addr = inet_addr(IP);

	if (bind(sock_fd,(struct sockaddr *)&addr_serv,sizeof(struct sockaddr_in)) < 0) {
		perror("bind error");
		exit(1);
	}

	if (listen(sock_fd,MAX_LISTEN) < 0) {
		perror("listen failed");
		exit(1);
	}

	while (1) {
		conn_fd = accept(sock_fd, (struct sockaddr *)&addr_client, &client_size);
		if (conn_fd < 0) {
			perror("accept failed");
			exit(1);
		}

		pid = fork();
		
		if (pid == 0) { // child proc 
			close(sock_fd);
			serve_proc(conn_fd);
		} else { // main proc
			close(conn_fd);
		}
	}
		
	close(sock_fd);
	return 0;
}

客户端(client.c)

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

#define REMOTE_IP "127.0.0.1"
#define REMOTE_PORT 1987

int main()
{
        int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (sock_fd < 0) {
                perror("create socket failed");
                exit(1);
        }

        struct sockaddr_in addr_serv;
        memset(&addr_serv, 0 ,sizeof(addr_serv));
        addr_serv.sin_family = AF_INET;
        addr_serv.sin_port = htons(REMOTE_PORT);
        addr_serv.sin_addr.s_addr = inet_addr(REMOTE_IP);

        if (connect(sock_fd, (struct sockaddr *)&addr_serv, sizeof(struct sockaddr)) < 0) {
                perror("connect failed");
                exit(1);
        }


        int send_num, recv_num;
        char send_buf[100],recv_buf[100];

        while (1) {
                printf("Input MSG: ");
                scanf("%s",send_buf);
                send_num = send(sock_fd, send_buf, strlen(send_buf), 0);
                if (send_num < 0) {
                        perror("send error");
                        exit(1);
                }

                recv_num = recv(sock_fd, recv_buf, sizeof(recv_buf), 0);
                if (recv_num < 0) {
                        perror("recv error");
                        exit(1);
                }
                recv_buf[recv_num] = '\0';
                printf("Got : %s\n", recv_buf);
        }

        close(sock_fd);
        return 0;
}
代码都很简单啦,就是基本的收发数据。不过需要注意的一点是 fork子进程以后需要对子进程关闭监听套接口,对父进程关闭连接套接口


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值