进程间传送句柄
不同进程间传送句柄是通过sendmsg和recvmsg函数发送和接收msghdr结构的辅助数据实现的.
struct msghdr
{
void *msg_name;
socklen_t msg_namelen;
struct iovec *msg_iov;
int msg_iovlen;
viod *msg_control;
socklen_t msg_controllen;
int msg_flags;
}
struct iovec
{
void *iov_base;
size_t iov_len;
}
struct cmsghdr
{
socklen_t cmsg_len;
int cmsg_level;
int cmsg_type;
/* data存放数据,数据的多少由用户决定 */
}
例子:
服务器端:
#include
#include
#include
#include
#include
#include
#define filename "/home/huang/temp.unix"
int main()
{
int s;
int client_s;
struct sockaddr_un addr;
struct sockaddr_un client_addr;
int len=sizeof(client_addr);
char buff[100];
int recv_num=0;
int n;
int file;
struct msghdr msg;
struct iovec iov;
struct cmsghdr cm;
struct cmsghdr *cmsghdrptr;
union
{
struct cmsghdr cm;
char data[CMSG_SPACE(sizeof(int))];
}control_msg;
bzero(buff,sizeof(buff));
iov.iov_base=buff;
iov.iov_len=sizeof(buff);
msg.msg_name=NULL;
msg.msg_namelen=0;
msg.msg_iov=&iov;
msg.msg_iovlen=1;
msg.msg_control=control_msg.data;
msg.msg_controllen=CMSG_SPACE(sizeof(int));
msg.msg_flags=0;
bzero(buff,sizeof(buff));
s=socket(AF_UNIX,SOCK_STREAM,0);
if(s<0)
{
printf("create socket fail\n");
exit(0);
}
unlink(filename);
bzero(&addr,sizeof(addr));
addr.sun_family=AF_UNIX;
strcpy(addr.sun_path,filename);
if(-1==bind(s,(struct sockaddr *)&addr,sizeof(addr)))
{
printf("bind socket fail\n");
exit(0);
}
chmod(filename,0777);
if(-1==listen(s,5))
{
printf("create listen socket fail!\n");
exit(0);
}
client_s=accept(s,(struct sockaddr *)&client_addr,&len);
recv_num=recvmsg(client_s,&msg,0);
if(recv_num==-1)
{
printf("recvmsg fail and the errno=%d\n",errno);
exit(0);
}
if((cmsghdrptr=CMSG_FIRSTHDR(&msg))!=NULL&&cmsghdrptr->cmsg_len==CMSG_LEN(sizeof(int)))
{
if(cmsghdrptr->cmsg_level!=SOL_SOCKET||cmsghdrptr->cmsg_type!=SCM_RIGHTS)
{
printf("paramter error!\n");
exit(0);
}
file=*((int *)CMSG_DATA(cmsghdrptr));
}
write(file,(char *)msg.msg_iov->iov_base,recv_num);
close(file);
close(client_s);
close(s);
unlink(filename);
return 1;
}
客户端:
include
#include
#include
#include
#include
#include
#include
#include
#define filename "/home/huang/temp.unix"
int main()
{
int s;
int client_s;
struct sockaddr_un addr;
char buff[100];
char ser_buff[15]="to the service";
int n;
int file;
struct msghdr msg;
struct iovec iov;
struct cmsghdr cm;
int number;
union
{
struct cmsghdr cm;
char data[CMSG_SPACE(sizeof(int))];
}control_msg;
struct cmsghdr *p;
iov.iov_base=ser_buff;
iov.iov_len=strlen(ser_buff);
printf("%d\n",iov.iov_len);
file=open("/home/huang/text.file",O_RDWR|O_CREAT);
printf("%s\n",ser_buff);
msg.msg_name=NULL;
msg.msg_namelen=0;
msg.msg_iov=&iov;
msg.msg_iovlen=1;
msg.msg_control=control_msg.data;
msg.msg_controllen=CMSG_SPACE(sizeof(int));
msg.msg_flags=0;
p=CMSG_FIRSTHDR(&msg);
p->cmsg_len=CMSG_LEN(sizeof(int));
p->cmsg_level=SOL_SOCKET;
p->cmsg_type=SCM_RIGHTS;
*((int *)CMSG_DATA(p))=file;
s=socket(AF_UNIX,SOCK_STREAM,0);
if(s<0)
{
printf("create socket fail\n");
exit(0);
}
bzero(&addr,sizeof(addr));
addr.sun_family=AF_UNIX;
strcpy(addr.sun_path,filename);
if(-1==connect(s,(struct sockaddr *)&addr,sizeof(addr)))
{
printf("connect socket fail and the errno=%d\n",errno);
exit(0);
}
number=sendmsg(s,&msg,0);
printf("%d\n",number);
if(number==-1)
{
printf("sendmsg fail and the errno= %d",errno);
exit(0);
}
close(s);
close(file);
return 1;
}
阅读(1042) | 评论(0) | 转发(0) |