2016-06-07 69 views
1

我一直在阅读博客和各种问题,因此试图了解如何使用Unix域套接字来传递文件描述符。但是,我不断收到sendmsg错误 - “传输端点未连接”。Unix域套接字传递文件描述符 - sendmsg:传输端点未连接

我很感激任何帮助了解我做错了什么。

服务器:

#include <stdio.h> 
#include <sys/socket.h> 
#include <sys/un.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <QDebug> 

char *socket_path = "/.socket"; 

ssize_t sock_fd_write(int sock, void *buf, ssize_t buflen, int fd) 
{ 
    ssize_t  size; 
    struct msghdr msg; 
    struct iovec iov; 
    union { 
     struct cmsghdr cmsghdr; 
     char  control[CMSG_SPACE(sizeof (int))]; 
    } cmsgu; 
    struct cmsghdr *cmsg; 

    iov.iov_base = buf; 
    iov.iov_len = buflen; 

    msg.msg_name = NULL; 
    msg.msg_namelen = 0; 
    msg.msg_iov = &iov; 
    msg.msg_iovlen = 1; 

    if (fd != -1) { 
     msg.msg_control = cmsgu.control; 
     msg.msg_controllen = sizeof(cmsgu.control); 

     cmsg = CMSG_FIRSTHDR(&msg); 
     cmsg->cmsg_len = CMSG_LEN(sizeof (int)); 
     cmsg->cmsg_level = SOL_SOCKET; 
     cmsg->cmsg_type = SCM_RIGHTS; 

     printf ("passing fd %d\n", fd); 
     *((int *) CMSG_DATA(cmsg)) = fd; 
    } else { 
     msg.msg_control = NULL; 
     msg.msg_controllen = 0; 
     printf ("not passing fd\n"); 
    } 

    printf ("sendmsg: %d\n", sock); 

    size = sendmsg(sock, &msg, 0); 

    if (size < 0) 
     perror ("sendmsg"); 
    return size; 
} 

int main(int argc, char *argv[]) { 
    struct sockaddr_un addr; 
    char buf[100]; 
    int fd,cl,rc; 

    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 
     perror("socket error"); 
     exit(-1); 
    } 

    qDebug() << "Created Socket"; 

    memset(&addr, 0, sizeof(addr)); 
    addr.sun_family = AF_UNIX; 
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1); 

    unlink(socket_path); 

    int reuse = 1; 
    int err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 
    if (0 == err) { 
     err = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); 
     if (err == -1) { 
      perror("bind error"); 
      exit(-1); 
     } 
    } 

    qDebug() << "Bound socket: " << fd; 

    if (listen(fd, 5) == -1) { 
     perror("listen error"); 
     exit(-1); 
    } 

    qDebug() << "Listening"; 

    while (1) { 

     qDebug() << "About to accept"; 

     if ((cl = accept(fd, NULL, NULL)) == -1) { 
      perror("accept error"); 
      qDebug() << "Accept error"; 
      continue; 
     } 

     while ((rc=read(cl,buf,sizeof(buf))) > 0) { 

      printf("read %u bytes: %.*s\n", rc, rc, buf); 

      qDebug() << "sock_fd_write: " << fd; 

      ssize_t size; 
      size = sock_fd_write(fd, (void*)"1", 1, 1); 
      printf ("wrote %d\n", size); 

     } 
     if (rc == -1) { 
      perror("read"); 
      exit(-1); 
     } 
     else if (rc == 0) { 
      printf("EOF\n"); 
      close(cl); 
     } 
    } 


    return 0; 
} 

客户:

#include <sys/socket.h> 
#include <sys/un.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <QDebug> 

char *socket_path = "/.socket"; 

ssize_t sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd) { 

    ssize_t  size; 

    if (fd) { 
     struct msghdr msg; 
     struct iovec iov; 
     union { 
      struct cmsghdr cmsghdr; 
      char  control[CMSG_SPACE(sizeof (int))]; 
     } cmsgu; 
     struct cmsghdr *cmsg; 

     iov.iov_base = buf; 
     iov.iov_len = bufsize; 

     msg.msg_name = NULL; 
     msg.msg_namelen = 0; 
     msg.msg_iov = &iov; 
     msg.msg_iovlen = 1; 
     msg.msg_control = cmsgu.control; 
     msg.msg_controllen = sizeof(cmsgu.control); 
     size = recvmsg (sock, &msg, 0); 
     if (size < 0) { 
      perror ("recvmsg"); 
      exit(1); 
     } 
     cmsg = CMSG_FIRSTHDR(&msg); 
     if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { 
      if (cmsg->cmsg_level != SOL_SOCKET) { 
       fprintf (stderr, "invalid cmsg_level %d\n", 
         cmsg->cmsg_level); 
       exit(1); 
      } 
      if (cmsg->cmsg_type != SCM_RIGHTS) { 
       fprintf (stderr, "invalid cmsg_type %d\n", 
         cmsg->cmsg_type); 
       exit(1); 
      } 

      *fd = *((int *) CMSG_DATA(cmsg)); 
      printf ("received fd %d\n", *fd); 
     } else 
      *fd = -1; 
    } else { 
     size = read (sock, buf, bufsize); 
     if (size < 0) { 
      perror("read"); 
      exit(1); 
     } 
    } 
    return size; 
} 

int main(int argc, char *argv[]) { 
    struct sockaddr_un addr; 
    char buf[100]; 
    int fd,rc; 

    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 
     perror("socket error"); 
     exit(-1); 
    } 

    qDebug() << "Socket connected"; 

    memset(&addr, 0, sizeof(addr)); 
    addr.sun_family = AF_UNIX; 
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1); 

    if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { 
     perror("connect error"); 
     exit(-1); 
    } 

    qDebug() << "Socket connected"; 

    ssize_t size; 

    int fdRead; 

    while((rc=read(STDIN_FILENO, buf, sizeof(buf))) > 0) { 

     qDebug() << "About to write"; 

     if (write(fd, buf, rc) != rc) { 

      if (rc > 0) { 

       qDebug() << "Partial write"; 

       size = sock_fd_read(fd, buf, sizeof(buf), &fdRead); 
       if (size <= 0) { 
        break; 
       } 
       printf("read %d\n", size); 
       if (fd != -1) { 
        write(fd, "hello, world\n", 13); 
        close(fd); 
       } 

      } 
      else { 

       perror("write error"); 
       exit(-1); 

      } 

     } 
    } 

    return 0; 

} 
+3

'sock_fd_write(fd,(void *)“1”,1,1)'。看起来你正在写'listen'套接字('fd')而不是'accept'套接字('cl')。 – kaylum

+0

谢谢 - 请在下面回答,我会接受答案并进行投票。 – PhilBot

回答

0

我需要使用接受插座 “CL”,而不是监听套接字 “FD”。

相关问题