利用Unix域套接字实现IPC

写完后,至少调试了30分钟时间。
错误1:
snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);
snprintf(argmode, sizeof(argmode), "%d", mode);
写作:
snprintf(argsockfd, sizeof(argsockfd), "%s", sockfd[1]);
snprintf(argmode, sizeof(argmode), "%s", mode);
错误2: msg.msg_control = unc;
msg.msg_controllen = sizeof(unc);
忘记初始化

疑点3:如果不断跳转到recvmsg,总是可以接收,并没有阻塞?不知道什么原因,明天再看看
解决:由于recvmsg返回为0时,表示TCP对端已经发送了FIN。此时应当退出


#include "unp.h"

#define unc un.control 

int my_open(const char *name, int mode);
int my_read(int fd, int *argfd);

int main(int argc, char **argv){
	int fd, n;
	char buf[MAXLINE];
	if((fd = my_open(argv[1], O_RDONLY)) < 0)
		err_sys("my_open");
	while((n = read(fd, buf, MAXLINE)) > 0)
		write(STDOUT_FILENO, buf, n);
	exit(0);
}

int my_open(const char *name, int mode){
	int sockfd[2], fd, status;
	pid_t tid; 
	char argsockfd[10], argmode[10];
	if(socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) < 0 )
		err_sys("pairsock");
	if((tid = fork( )) < 0)
		err_sys("fork");
	else if(tid == 0){/*child进程*/
		#ifdef DEBUG
			printf("child exec\n");
		#endif
		close(sockfd[0]);
		snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);
		snprintf(argmode, sizeof(argmode), "%d", mode);
		execl("./openfile", "openfile",  argsockfd, 
			argmode, name, (char *)NULL);
		err_sys("execl");		
	}
	/*parent进程*/
	close(sockfd[1]);
	waitpid(tid, &status, 0);
	#ifdef DEBUG
		sleep(5);
	#endif
	if(my_read(sockfd[0], &fd) < 0)/*读取描述符*/
		return  -1;
	close(sockfd[0]);
	return fd;
}


int my_read(int fd, int *argfd){
	int n;
	char *buf = malloc(sizeof(char));
	struct msghdr msg;
	struct cmsghdr *cmsg;
	union{
		struct cmsghdr cm;
		char   control[CMSG_SPACE(sizeof(int))];
	}un;
	struct iovec iov[1];
	iov[0].iov_base = buf;
	iov[0].iov_len = 1;
	bzero(&msg, sizeof(msg));
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_control = unc;
	msg.msg_controllen = sizeof(unc);
	//msg.msg_flags = 0;
again:
	if((n = recvmsg(fd, &msg, 0)) <= 0){
		if(errno == EINTR)
			return -1;
		else
			goto again;
	}
	free(buf);
	buf = NULL;
	#ifdef DEBUG
		printf("recv is complete  %d\n", n);
		goto again;
	#endif
	cmsg = CMSG_FIRSTHDR(&msg);
	if(cmsg == NULL){
			return -1;
	}
	if(cmsg->cmsg_len != CMSG_LEN(sizeof(int))){
		return -1;
	}
	if((cmsg->cmsg_level == SOL_SOCKET)&&(cmsg->cmsg_type == SCM_RIGHTS)){
		*argfd = *(int *)CMSG_DATA(cmsg);
	}
	else
		*argfd = -1;
	return 0;
}

/*示范1*/
#include "unp.h"
#define unc un.control
int my_write(int openfd, int fd);

int main(int argc, char **argv){
	int fd, openfd;
	if((fd = open(argv[3], atoi(argv[2]))) < 0)
		err_sys("open");
	openfd = atoi(argv[1]);
	if(my_write(openfd, fd) < 0)/*利用openfd套接口将fd发送给父进程*/
		err_sys("my_write");
	close(fd);
	exit(0);
}

int my_write(int openfd, int fd){
	int n;
	char *c = malloc(sizeof(char));
	struct msghdr msg;
	struct cmsghdr *cmsg;
	struct iovec iov[1];
	union{
		struct cmsghdr cm;
		char control[CMSG_SPACE(sizeof(int))];
	}un;
	*c = 'a';
	iov[0].iov_base = c;
	iov[0].iov_len = 1;
	bzero(&msg, sizeof(msg));
	msg.msg_control = unc;
	msg.msg_controllen = sizeof(unc);
	cmsg = CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type = SCM_RIGHTS;
	*(int *)CMSG_DATA(cmsg) = fd;
	msg.msg_name  = NULL;
	msg.msg_namelen = 0;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_flags = 0;
		
again:
	if((n = sendmsg(openfd, &msg, 0) ) < 0){
		if(errno == EINTR)
			goto again;
		else
			return -1;
	}
	//sleep(5);
	free(c);
	c = NULL;
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值