09 TCP套接字之并发服务端


前面实现了简单的网络通信, 但是随之而来还是很多的问题. 比如为什么只能建立一个连接; 为什么服务端先断开会有客户端还没有响应断开等等. 问题我们一个个来解决, 本节就先来解决连接问题.


多进程

我们可以为每一个连接重新创建一个进程, 这样就可以实现每次只能连接一个的问题了. 同样多进程可以解决, 那么多线程也可以解决, 而现在先以进程解决, 后面我们再来以线程解决.

一般我们都是将客服端和服务端的代码写在一起, 通过不同的选项来实现不同的功能. 而一次性的代码量又可能有点多, 所以就将修改比较重要的部分罗列出来分析.


该代码将通信中的两个代码合并了一下. 完整代码 service_fork.c.

这里我们主要看服务端的修改 :

// 服务端
int service(int port, const char *ser_addr)
{
    int sockfd, clientfd;
    sockfd = Socket(0);
    Bind(sockfd, port, ser_addr);
    listen(sockfd, 1);

    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);

    char buf[1024];
    int n;
    pid_t pid;
    while(1)
    {
	clientfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
	if((pid = fork()) < 0)
	    EXIT("fork");
	else if(0 == pid)
	{
	    close(sockfd);
	    while(1)
	    {
		n = recv(clientfd, buf, sizeof(buf), 0);
		if(0 == n)
		    break;
		send(clientfd, buf, n, 0);
	    }
	    close(clientfd);
	    exit(0);
	}
	close(clientfd);
    }

    close(clientfd);
    close(sockfd);

    return 0;
}

服务端每次有新的连接就创建一个子进程. 因为fork后的子进程会复制所有父进程的文件描述符, 而对于子进程来说他只管连接一端的套接字, 监听套接字在子进程没有意义, 所以子进程第一个步骤就是close(sockfd). 同理, 父进程对连接的套接字是交给子进程来完成的, 所以父进程第一个步骤就是close(client).


编译运行. 服务端运行 :

./a.out 1 8080 192.168.1.16

客户端运行 :

./a.out 2 8080 192.168.1.16

在这里插入图片描述

新问题

上面我们用fork解决了只能连接一个的问题, 但是现在又有一个新的问题出现了. 恩? 刚解决一个问题又来一个新的问题? 啥问题?

在这里插入图片描述

上面我将两个客户端关闭, 结果呢, 服务端的两个子进程的资源没有被回收从而成为了僵尸进程了. 这个问题的解决我们放到下节来解决


总结

后面也验证了一下本机能够支持多进程连接的实验. 最大保持TCP连接的个数.

  • 并发编程就是让程序能“同时”处理多个任务.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值