Linux socke server编程:父进程和子进程关系

Linux socke server编程:父进程和子进程关系

测试过程中碰到的需要记录的地方

1、父进程accept创建新socket后(比如socket为connect_fd),需要在父进程中关闭该connect_fd(即close(connect_fd))(父进程负责accept等待创建连接,每次产生新的连接交给子进程处理的情况下)
因为:子进程是父进程的完全拷贝,所以只有父子两个进程都关掉connect_fd,这个connect_fd才算关掉;如果父进程这里没有close(connect_fd),那就算子进程close(connect_fd),实际socket connect_fd并没有被关闭; 所以为了子进程完全控制connect_fd,父进程创建connect_fd后,直接close(connect_fd);

完整代码

下面展示 TCP server端代码

/* File Name: server.c */  
#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<errno.h>  
#include<sys/types.h>  
#include<unistd.h>/*#包含<unistd.h> fork()等程序会用到*/
#include<arpa/inet.h>/**/
#include<sys/socket.h>  
#include<netinet/in.h>  
#define DEFAULT_PORT 40010  
#define MAXLINE 4096  
int main(int argc, char** argv)  
{  
	int    socket_fd, connect_fd;  
	struct sockaddr_in     servaddr;  
	char    buff[4096];  
	int     n;  
	//初始化Socket     
	if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){  
		printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);  
		exit(0);  
	}  
	//初始化  
	memset(&servaddr, 0, sizeof(servaddr));  
	servaddr.sin_family = AF_INET;  
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。  
	//   printf("servaddr.sin_addr_cxf == %s\n",inet_ntoa((struct in_addr) servaddr.sin_addr)); 
	servaddr.sin_port = htons(DEFAULT_PORT);//设置的端口为DEFAULT_PORT  

	//将本地地址绑定到所创建的套接字上  
	if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){  
		printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);  
		exit(0);  
	}  
	//开始监听是否有客户端连接  
	if( listen(socket_fd, 10) == -1){  
		printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);  
		exit(0);  
	}  
	printf("======waiting for client's request======\n");  
	printf("main PID == %d\n",getpid());
	while(1){  
		//阻塞直到有客户端连接,不然多浪费CPU资源。  
		if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1){  
			printf("accept socket error: %s(errno: %d)",strerror(errno),errno);  
			continue;  
		}		
		if(!fork())
		{
			printf("son PID == %d\n",getpid());
			printf("connect_fd == %d\n",connect_fd); 
			if(send(connect_fd, "Hello,you are connected!\n", 26,0) == -1)  
				perror("send error");
			while(1)
			{
				//接受客户端传过来的数据  
				if((n = recv(connect_fd, buff, MAXLINE, 0))== 0)                  //这里要判断recv接收到的是否为0,不然client主动断开后,会导致一直打印"recv msg from client: %s,PID:%d \n"
				{
					printf("closed from client,connect_fd:%d\n",connect_fd);
					close(connect_fd);
					exit(0);				
				}
				buff[n] = '\0'; 
				printf("connect_fd:%d \n", connect_fd);  
				printf("recv msg from client: %s,PID:%d \n", buff,getpid());  
			}	
		}
		close(connect_fd);           //这里是父进程的connect_fd,需要着重讲下:父子进程都有这个connect_fd标识符,只有父子两个进程都关掉connect_fd,这个connect_fd才算关掉;如果父进程这里没有close(connect_fd),那就算子进程close(connect_fd),实际socket connect_fd并没有被关闭; 所以为了子进程完全控制connect_fd,父进程创建connect_fd后,直接close(connect_fd)
	}  
	close(socket_fd);  
}  

注意点

1、fork()之后,创建新进程(即子进程),通过sudo netstat -antup可以查看原进程和新进程;
2、可以通过getpid()获取本进程的进程ID(即PID);
3、如果子进程结束,但是子进程的某些资源没关掉的话,会导致进程被挂到父进程下面

比如子进程中没有close(connect_fd),但是子进程调用了exit(0)关闭自己的线程,然后从sudo netstat -antup来看,子线程还在,只不过PID变成了父进程的PID
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux Socket编程是指在Linux操作系统下使用Socket API进行网络编程的过程。Socket是用于在计算机网络之间进行通信的一种机制,它提供了一种标准的、可移植的接口,使得不同操作系统之间的程序可以进行网络通信。在Linux系统下,Socket API是一个非常强大的网络编程接口,它提供了一系列的函数和数据结构,可以方便地实现各种网络应用程序。 Socket编程的基本原理是通过创建Socket对象,在网络上建立连接,然后进行数据的传输和接收。在Linux系统下,Socket编程主要包括以下步骤: 1. 创建Socket对象:使用socket函数创建Socket对象,并指定协议类型和套接字类型。 2. 绑定Socket对象:使用bind函数将Socket对象与本地IP地址和端口号进行绑定。 3. 监听Socket对象:使用listen函数将Socket对象转换为被动套接字,等待客户端的连接请求。 4. 接受连接:使用accept函数接受客户端的连接请求,返回一个新的Socket对象,用于与客户端进行通信。 5. 发送和接收数据:使用send和recv函数进行数据的发送和接收。 6. 关闭Socket对象:使用close函数关闭Socket对象,释放资源。 在进行Socket编程时,需要注意以下几点: 1. Socket编程需要对网络编程有一定的了解,包括TCP/IP协议、网络编程模型等。 2. 处理网络编程中可能出现的错误,例如连接超时、网络中断等。 3. Socket编程需要考虑网络安全问题,例如数据加密、防止拒绝服务攻击等。 总之,Socket编程网络编程中非常重要的一部分,如果您想要进行网络编程开发,那么对Socket编程的掌握是必不可少的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值