- 论坛徽章:
- 0
|
各位大虾,帮帮忙!
我有一个项目,需要从子进程将打开的套接字描述字传递回父进程,本来现在大多数UNIX和Linux都支持通过UNIX域套接字从一个进程将描述字传到另一个进程,在Linux上我测试没有问题,但同样的程序在SCO OpenServer5.0.5下通不过,程序告诉我不行。不知道SCO 下是否支持描述字在不同进程传递?
/* 服务进程 */
#include <stdio.h>;
#include <sys/errno.h>;
#include <sys/types.h>;
#include <sys/socket.h>;
#include <sys/un.h>;
#include <unistd.h>;
#include <sys/uio.h>;
#include <fcntl.h>;
extern int errno;
void DoDisplay( int );
void main() {
int serverfd, connfd;
struct sockaddr_un servaddr, cliaddr;
int child, clilen;
serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (serverfd < 0) {
printf("parent: create socket failed!\n" ;
exit(-1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, tmpnam(NULL));
bind(serverfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(serverfd, 1024);
printf("parent: server listen at %s...\n", servaddr.sun_path);
{
char s[200];
sprintf(s, "echo \"./son %s\">;s.sh", servaddr.sun_path);
system(s);
}
for (; {
clilen = sizeof(cliaddr);
if ( (connfd = accept(serverfd, (struct sockaddr *)&cliaddr, &clilen)) < 0)
{
if (errno == EINTR)
continue;
else
{
printf("parent: accept failed!\n" ;
exit(-1);
}
}
if ( (child = fork()) == 0) {
printf("parent: fork one .\n" ;
close(serverfd);
DoDisplay(connfd);
exit(0);
}
close(connfd);
}
}
void DoDisplay( int connfd ) {
char buf[1025];
int nbytes;
char c;
int fd;
if (read_fd(connfd, &c, 1, &fd) < 0) {
printf(" arent: read_fd failed!\n" ;
exit(-1);
}
printf("parent: file %d\n", fd);
while ( (nbytes = read(fd, buf, 1024)) >; 0 ){
printf("Read %d bytes\n", nbytes);
buf[nbytes] = 0;
printf("%s", buf);
}
close(connfd);
close(fd);
}
void err_quit(char *s) {
printf("%s\n", s);
exit(-1);
}
int read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
struct msghdr msg;
struct iovec iov[1];
ssize_t n;
int newfd;
#define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size))
#define CMSG_LEN(size) (sizeof(struct cmsghdr) + (size))
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
if ( (n = recvmsg(fd, &msg, 0)) <= 0)
return(n);
if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
cmptr->;cmsg_len == CMSG_LEN(sizeof(int))) {
if (cmptr->;cmsg_level != SOL_SOCKET)
err_quit("control level != SOL_SOCKET" ;
if (cmptr->;cmsg_type != SCM_RIGHTS)
err_quit("control type != SCM_RIGHTS" ;
*recvfd = *((int *) CMSG_DATA(cmptr));
} else
*recvfd = -1; /* descriptor was not passed */
return(n);
}
/* 客户进程 */
#include <stdio.h>;
#include <sys/errno.h>;
#include <sys/types.h>;
#include <sys/socket.h>;
#include <sys/un.h>;
#include <unistd.h>;
#include <sys/uio.h>;
#include <fcntl.h>;
void DoSend( int fd );
int write_fd(int fd, void *ptr, size_t nbytes, int sendfd);
void main(int argc, char **argv) {
int sockfd, ret;
struct sockaddr_un servaddr;
if (argc != 2) {
printf("Usage: %s serverfilename \n", argv[0]);
exit(-1);
}
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("son:create socket failed!\n" ;
exit(-1);
}
bzero( &servaddr, sizeof(servaddr) );
servaddr.sun_family = AF_UNIX;
strcpy(servaddr.sun_path, argv[1]);
ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (ret < 0) {
printf("son: connect failed!\n" ;
exit(-1);
}
DoSend(sockfd);
exit(0);
}
void DoSend( int fd ) {
int sendfd;
int n;
if ( (sendfd = open("readme", O_RDONLY)) < 0) {
printf("son: open readme error!\n" ;
exit(-1);
}
printf("son: file %d\n", sendfd);
if ( (n = write_fd(fd, " ", 1, sendfd)) < 0)
printf("son: write fd error!\n");
exit(-1);
}
int write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
struct msghdr msg;
struct iovec iov[1];
#define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size))
#define CMSG_LEN(size) (sizeof(struct cmsghdr) + (size))
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
cmptr = CMSG_FIRSTHDR(&msg);
cmptr->;cmsg_len = CMSG_LEN(sizeof(int));
cmptr->;cmsg_level = SOL_SOCKET;
cmptr->;cmsg_type = SCM_RIGHTS;
*((int *) CMSG_DATA(cmptr)) = sendfd;
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
return(sendmsg(fd, &msg, 0));
} |
|