首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

UNIX domain socket传接文件描述符

2012-08-30 
UNIX domain socket传递文件描述符c版本(UNIX高级编程中的例子):?// sendmsg.h#ifndef SENDMSG_H#define S

UNIX domain socket传递文件描述符

c版本(UNIX高级编程中的例子):

?

// sendmsg.h#ifndef SENDMSG_H#define SENDMSG_H#include <sys/types.h>int send_fd(int fd, int fd_to_send);int recv_fd(int fd, ssize_t (*userfunc)(int, const void*, size_t));#endif

?

?

// semdmsg.c#include "sendmsg.h"#include <sys/socket.h>#include <stdio.h>#include <stdlib.h>static struct cmsghdr* cmptr = NULL;static int CONTROLLEN = sizeof(struct cmsghdr) + sizeof(int);static int MAXLINE = 100;int send_fd(int fd, int fd_to_send){struct iovec iov[1];struct msghdr msg;char buf[2];iov[0].iov_base = buf;iov[0].iov_len = 2;msg.msg_iov = iov;msg.msg_iovlen = 1;msg.msg_name = NULL;msg.msg_namelen = 0;if (fd_to_send <= 0){return -1;}if (cmptr == NULL && (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL)return -1;cmptr->cmsg_level = SOL_SOCKET;cmptr->cmsg_type = SCM_RIGHTS;cmptr->cmsg_len = CONTROLLEN;msg.msg_control = cmptr;msg.msg_controllen = CONTROLLEN;*(int*)CMSG_DATA(cmptr) = fd_to_send;buf[1] = 0;buf[0] = 0;if (sendmsg(fd, &msg, 0) != 2)return -1;return 0;}int recv_fd(int fd, ssize_t (*userfunc)(int, const void*, size_t)){int newfd, nr, status;char *ptr;char buf[MAXLINE];struct iovec iov[1];struct msghdr msg;status = -1;for ( ; ; ){iov[0].iov_base = buf;iov[0].iov_len = sizeof(buf);msg.msg_iov = iov;msg.msg_iovlen = 1;msg.msg_name = NULL;msg.msg_namelen = 0;if (cmptr == NULL & (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL){return -1;}msg.msg_control = cmptr;msg.msg_controllen = CONTROLLEN;if ((nr = recvmsg(fd, &msg, 0)) < 0){//err_sys("recvmsg error");}else if (nr == 0){//err_ret("connection closed by server");return -1;}for (ptr = buf; ptr < &buf[nr]; ){if (*ptr++ == 0){if (ptr != &buf[nr-1]){//err_dump("message format error");}status = *ptr & 0xFF;if (status == 0){if (msg.msg_controllen != CONTROLLEN){//err_dump("status = 0but no fd");}newfd = *(int*)CMSG_DATA(cmptr);}else{newfd = -status;}nr -= 2;}}//if (nr > 0 && (&userfunc)(STDERR_FILENO, buf, nr) != nr)//{//return -1;//}if (status >= 0)return newfd;}}

?

?

c++版本,自己封装的:

?

//domainsocket.h/* * domainsocket.h * *  Created on: Apr 13, 2012 *      Author: song */#ifndef DOMAINSOCKET_H_#define DOMAINSOCKET_H_#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/un.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>#include <errno.h>#include <sys/stat.h>#include <fcntl.h>class DomainSocket{// the exact name of this class may be "DomainSocketListener"// but we call it "DomainSocket" temporarypublic:DomainSocket();virtual ~DomainSocket();int Bind(const char* path);int Listen(int n);int Accept();int Connect(const char* path);// client call this to send dataint Send(const void* buf, size_t len, int flags);// server call this to send dataint Send(int sockfd, const void* buf, size_t len, int flags);// client receiveint Recv(void *buf, size_t len, int flags);// server receiveint Recv(int sockfd, void *buf, size_t len, int flags);/* * the four methods below used to send and receive file descriptor. * if you are server, you have one more argument than client whatever * send or receive. * */// send file descriptor// domain socket client send fd need call this.int Sendfd(int fdToSend);// domain socket server send fd need call this.int Sendfd(int sockfd, int fdToSend);// received file descriptor as return value// return ://              > 0 all right!//              = 0 receive failint Recvfd();// received file descriptor as return value// ... ... ... ...int Recvfd(int sockfd);protected:void DelDSocketFilePath();private:int m_fd;struct sockaddr_un m_addr;const char* m_path;struct cmsghdr* cmptr;int CONTROLLEN;int MAXLINE;int _Sendfd(int sockfd, int fdToSend);int _Recvfd(int sockfd);};#endif /* DOMAINSOCKET_H_ */

?

?

//domainsocket.cpp#include "domainsocket.h"using namespace std;DomainSocket::DomainSocket(){m_fd = 0;m_path = NULL;cmptr = NULL;CONTROLLEN = sizeof(struct cmsghdr) + sizeof(int);MAXLINE = 100;//////////////////////////////////int len;memset(&m_addr, 0, sizeof(m_addr));if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){cout<<"create domain socket fail!"<<endl;//return -1;}cout<<"create domain socket ... , fd is '"<<m_fd<<"'"<<endl;}DomainSocket::~DomainSocket(){close(m_fd);DelDSocketFilePath();}int DomainSocket::Bind(const char* path){m_path = path;// if file exist delete itDelDSocketFilePath();m_addr.sun_family = AF_UNIX;strcpy(m_addr.sun_path, (char*)m_path);// bindif (bind(m_fd, (struct sockaddr*)&m_addr, sizeof(m_addr)) < 0){cout<<"domain bind fail!, errno is '"<<errno<<"' [reason:"<<strerror(errno)<<"]"<<endl;close(m_fd);DelDSocketFilePath();return -1;}cout<<"domain bind (socket and sockaddr) ..."<<endl;return 0;}int DomainSocket::Listen(int n){if (listen(m_fd, n) < 0){cout<<"domain listen fail!, errno is '"<<errno<<"' [reason:"<<strerror(errno)<<"]"<<endl;close(m_fd);DelDSocketFilePath();return -1;}cout<<"domain listen ..."<<endl;return 0;}int DomainSocket::Accept(){struct sockaddr cli_addr;int new_fd;int len = sizeof(cli_addr);if ((new_fd = accept(m_fd, (struct sockaddr*)&cli_addr, (socklen_t*)&len)) < 0){cout<<"domain accept fail!, errno is '"<<errno<<"' [reason:"<<strerror(errno)<<"]"<<endl;close(m_fd);DelDSocketFilePath();return -1;}cout<<"  domain accept a new fd '"<<new_fd<<"'"<<endl;return new_fd;}int DomainSocket::Connect(const char* path){sockaddr_un server_addr;server_addr.sun_family = AF_UNIX;strcpy(server_addr.sun_path, path);if (connect(m_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){cout<<"connect fail, err msg: "<<strerror(errno)<<endl;close(m_fd);return -1;}}int DomainSocket::Send(const void *buf, size_t len, int flags){return send(m_fd, buf, len, flags);}int DomainSocket::Send(int sockfd, const void *buf, size_t len, int flags){return send(sockfd, buf, len, flags);}int DomainSocket::Recv(void *buf, size_t len, int flags){return recv(m_fd, buf, len, flags);}int DomainSocket::Recv(int sockfd, void *buf, size_t len, int flags){return recv(sockfd, buf, len, flags);}int DomainSocket::Sendfd(int fdToSend){return _Sendfd(m_fd, fdToSend);}int DomainSocket::Sendfd(int sockfd, int fdToSend){return _Sendfd(sockfd, fdToSend);}int DomainSocket::Recvfd(){return _Recvfd(m_fd);}int DomainSocket::Recvfd(int sockfd){return _Recvfd(sockfd);}int DomainSocket::_Sendfd(int sockfd, int fdToSend){struct iovec iov[1];struct msghdr msg;char buf[2];iov[0].iov_base = buf;iov[0].iov_len = 2;msg.msg_iov = iov;msg.msg_iovlen = 1;msg.msg_name = NULL;msg.msg_namelen = 0;if (fdToSend <= 0){return -1;}if (cmptr == NULL && (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL)return -1;cmptr->cmsg_level = SOL_SOCKET;cmptr->cmsg_type = SCM_RIGHTS;cmptr->cmsg_len = CONTROLLEN;msg.msg_control = cmptr;msg.msg_controllen = CONTROLLEN;*(int*)CMSG_DATA(cmptr) = fdToSend;buf[1] = 0;buf[0] = 0;if (sendmsg(sockfd, &msg, 0) != 2)return -1;return 0;}int DomainSocket::_Recvfd(int sockfd){int newfd, nr, status;char *ptr;char buf[MAXLINE];struct iovec iov[1];struct msghdr msg;status = -1;for ( ; ; ){iov[0].iov_base = buf;iov[0].iov_len = sizeof(buf);msg.msg_iov = iov;msg.msg_iovlen = 1;msg.msg_name = NULL;msg.msg_namelen = 0;if (cmptr == NULL & (cmptr = (struct cmsghdr*)malloc(CONTROLLEN)) == NULL){return -1;}msg.msg_control = cmptr;msg.msg_controllen = CONTROLLEN;if ((nr = recvmsg(sockfd, &msg, 0)) < 0){//err_sys("recvmsg error");}else if (nr == 0){//err_ret("connection closed by server");return -1;}for (ptr = buf; ptr < &buf[nr]; ){if (*ptr++ == 0){if (ptr != &buf[nr-1]){//err_dump("message format error");}status = *ptr & 0xFF;if (status == 0){if (msg.msg_controllen != CONTROLLEN){//err_dump("status = 0but no fd");}newfd = *(int*)CMSG_DATA(cmptr);}else{newfd = -status;}nr -= 2;}}//if (nr > 0 && (&userfunc)(STDERR_FILENO, buf, nr) != nr)//{//return -1;//}if (status >= 0)return newfd;}}void DomainSocket::DelDSocketFilePath(){if (!m_path)return;unlink(m_path);}

?

热点排行