학습자료(~2017)/리눅스

[Linux] 유닉스 소켓 (unix socket) 을 이용한 파일 디스크립트 보내기/받기(file descriptor send/recv) - 다른 프로세스로 디스크립트 전송/공유

단세포소년 2013. 5. 24. 17:07
반응형

리눅스는 유닉스 소켓을 이용하여 프로세스끼리 파일 디스크립트를 보내주고 받을 수 있다.

아래 예제는 뼈대만 존재한다. 예외나 기타 처리는 없다.

뼈대에 살을 붙이는 형태로 사용 할 것이다.

자세한 설명은 나중에.. 시간이 있다면...


 sender.c - 이 예제에서는 sender 프로세스가 자신의 표준출력 디스크립트를 전송

 #include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<unistd.h>

#include<sys/un.h>




int main(int argc,char **args)

{

    int sc;

    struct sockaddr_un addr;

    int z;

    int fd;


    sc = socket(PF_LOCAL,SOCK_STREAM,0);

    if(sc < 0)

    {


        return -1;

    }


    memset(&addr,sizeof(addr),0);

    addr.sun_family = AF_LOCAL;

    strncpy(addr.sun_path,"zSOCKET-SERVER", sizeof(addr.sun_path) -1);

    addr.sun_path[0] = 0;


    z = connect(sc,&addr,sizeof(addr));

    if(z < 0)

    {

        return -1;

    }



    struct msghdr msgh;

    struct iovec iov[1];

    struct cmsghdr *cmsgp = NULL;

    char buf[CMSG_SPACE(sizeof(int))];

    int er=99;



  //  msgh.msg_name = &addr;

  //  msgh.msg_namelen = sizeof(addr);


    msgh.msg_name = NULL;

    msgh.msg_namelen = 0;


    msgh.msg_iov = iov;

    msgh.msg_iovlen = 1;


    iov[0].iov_base = &er;

    iov[0].iov_len = sizeof(er);



    msgh.msg_control = buf;

    msgh.msg_controllen = sizeof(buf);



    cmsgp = CMSG_FIRSTHDR(&msgh);

    cmsgp->cmsg_level = SOL_SOCKET;

    cmsgp->cmsg_type = SCM_RIGHTS;

    cmsgp->cmsg_len = CMSG_LEN(sizeof(fd));



    //보낼 파일디스크립터 지정

    fd = fileno(stdout);

    *((int *)CMSG_DATA(cmsgp) ) = fd;



    msgh.msg_controllen = cmsgp->cmsg_len;



    sendmsg(sc,&msgh,0);


    close(sc);

    return 0;

}



recver.c - sender 프로세스가 보낸 파일 디스크립트에 "test" 란 문자열을 쓴다.

 #include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<unistd.h>

#include<sys/un.h>

#include<string.h>

#include<errno.h>








int main()

{

    int server_sc;

    struct sockaddr_un server_addr;

    struct sockaddr_un client_addr;

    socklen_t len;

    int er;



    server_sc = socket(PF_LOCAL,SOCK_STREAM,0);

    if(server_sc < 0)

    {

        perror("");


        return -1;

    }


    memset(&server_addr,0,sizeof(server_addr));


    server_addr.sun_family = AF_LOCAL;

    strncpy(server_addr.sun_path,"zSOCKET-SERVER", sizeof(server_addr.sun_path) -1);

    server_addr.sun_path[0] = 0;


    er = bind(server_sc,&server_addr,sizeof(server_addr));

    if(er < 0)

    {

        perror("");


        return -1;

    }



    listen(server_sc,4);


    while(1)

    {

     int fd;

     int rlen;

     len= sizeof(client_addr);

     fd = accept(server_sc,&client_addr,&len);

     if(fd < 0)

     {

       return -1;

     }


   

     int recv_fd;


     struct msghdr msgh;

     struct iovec iov[1];


     struct cmsghdr * cmsgp = NULL;

     char buf [CMSG_SPACE(sizeof(int))];

     char dbuf[80];

     int er;


     memset(&msgh,0,sizeof(msgh));

     memset(buf,0,sizeof(buf));


     msgh.msg_name = NULL;

     msgh.msg_namelen = 0;


     msgh.msg_iov = iov;

     msgh.msg_iovlen = 1;


     iov[0].iov_base = &er;

     iov[0].iov_len = sizeof(er);


     msgh.msg_control = buf;

     msgh.msg_controllen = sizeof(buf);



     

      recvmsg(fd,&msgh,0);



    // printf("recvmsg end  iov = %d\n",*((int *)iov[0].iov_base));



     for(cmsgp = CMSG_FIRSTHDR(&msgh);cmsgp != NULL ; cmsgp = CMSG_NXTHDR(&msgh,cmsgp))

     {    printf("for \n");

         if(cmsgp->cmsg_level == SOL_SOCKET && cmsgp->cmsg_type == SCM_RIGHTS)

         {

            

             recv_fd = *((int *)CMSG_DATA(cmsgp));

             write(recv_fd,"test",strlen("test"));

         }



     }


     close(fd);



    }


    return 0;

}



반응형