socket进程间通信

来源:互联网 发布:淘宝可以讲价吗 编辑:程序博客网 时间:2024/05/11 00:55

//----------------------------------------------------

//AUTHOR: lanyang123456

//DATE: 2014-10-20

//----------------------------------------------------



socket在主机间和进程间使用,方法类似,主要区别是进程间通信使用的是sockaddr_un,而主机间的通信使用的是sockadd_in。


每个套接字都有其自己的地址格式,对于AF_UNIX域套接字来说,它的地址由结构sockaddr_un来描述,该结构定义在头文件sys/un.h中,它的定义如下:


struct sockaddr_un{      sa_family_t sun_family;//AF_UNIX,它是一个短整型      char        sum_path[];//路径名  <pre name="code" class="cpp">};

对于AF_INET域套接字来说,它的地址结构由sockaddr_in来描述,它至少包括以下几个成员:
    struct sockaddr_in{          short int            sin_family;//AF_INET          unsigned short int    sin_port;//端口号          struct in_addr        sin_addr;//IP地址      };  




而in_addr被定义为:

<span style="font-size:14px;">struct in_addr{      unsigned long int s_addr;  };  </span>




使用socket作为进程间通信方式,有什么注意事项?

(1) Server

 a. 创建一个server socket

  创建的socket是AF_UNIX域的。

 b. 设置Server的地址

   利用bind函数。

  注意:地址一般通过一个字符串来标识,一般的做法是通过一个Linux路径来实现;注意使用之前必须要把该路径unlink掉,否则可能出现bind失败的情况。

 c. 开始监听

   利用listen函数。

   注意:最大监听的长度为128.

  d. 接客

   利用accept函数。

  注意:accept函数默认为阻塞模式。有一个可以设置非阻塞的为accept4函数;

         在accept函数阻塞的过程中,一些信号对打断accept的阻塞,这是正常现象。因此如果要设置一直阻塞,需要考虑这种情况。

  e. 收钱

   利用recv()函数

   注意:recv函数是在accept新生成的socket上接收消息。recv()函数可以工作在阻塞模式,也可以工作在非阻塞模式。一般都是阻塞模式。新生成的socket注意要关闭。

(2) client

 a. 创建

   注意域为AF_UNIX。

  b. 连接服务器:connect调用

  注意:connect为非阻塞模式,需要增加重试机制保证可靠性。

  c. 发送数据:send

  注意:该调用可以是阻塞的,也可以是非阻塞的,最好设置为非阻塞模式,默认为阻塞模式。另外,可以调用setsockopt()来设置阻塞时长。level:SOL_SOCKET,SO_SNDTIMEO。


例子如下:

server


/*IPCsocket AF_UNIXserver*/#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h> #include <errno.h>#define UNIX_DOMAIN"/tmp/UNIX.domain"#define QUEUE_LEN5int main(void){    socklen_t clt_addr_len;    int listen_fd;    int com_fd;    int ret;    int i;    char recv_buf[1024];     int len;    struct sockaddr_un client_addr;    struct sockaddr_un server_addr;    listen_fd=socket(PF_UNIX, SOCK_STREAM, 0);    if(listen_fd < 0)    {        perror("cannot create communication socket");        return -1;    }          //set server addr    server_addr.sun_family = AF_UNIX;    strncpy(server_addr.sun_path, UNIX_DOMAIN, sizeof(server_addr.sun_path) - 1);    unlink(UNIX_DOMAIN);    //bind sockfd & addr    ret = bind(listen_fd, (struct sockaddr*)&server_addr,sizeof(server_addr));    if(ret == -1)    {        perror("cannot bind server socket");        close(listen_fd);        unlink(UNIX_DOMAIN);        return -1;    }    //listen sockfd     ret = listen(listen_fd, 1);    if(ret==-1)    {        perror("cannot listen the client connect request");        close(listen_fd);        unlink(UNIX_DOMAIN);        return -1;    }    //have connect request use accept    len = sizeof(client_addr);    com_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len);    if(com_fd < 0)    {        perror("cannot accept client connect request");        close(listen_fd);        unlink(UNIX_DOMAIN);        return -1;    }    //read and printf sent client info    printf("---------------\n");      memset(recv_buf,0,1024);    ret = read(com_fd, recv_buf, sizeof(recv_buf) - 1);    if (ret <= 0)     {printf("write error(%d) %s\n", errno, strerror(errno));close(com_fd);    close(listen_fd);    unlink(UNIX_DOMAIN);    return -1;    }    printf("Message from client :%s\n", recv_buf);      close(com_fd);    close(listen_fd);    unlink(UNIX_DOMAIN);    return 0;}


client


/*IPCsocket AF_UNIXclient*/#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <errno.h>#define UNIX_DOMAIN "/tmp/UNIX.domain"int main(void){    int connect_fd;    int ret;    char snd_buf[1024];    int i;    static struct sockaddr_un server_addr;    //creat unix socket    connect_fd=socket(AF_UNIX, SOCK_STREAM, 0);    if(connect_fd<0)    {        perror("cannot create communication socket");        return 1;    }    server_addr.sun_family = AF_UNIX;    strcpy(server_addr.sun_path, UNIX_DOMAIN);    //connect server    ret=connect(connect_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));    if(ret==-1)    {        perror("cannot connect to the server");        close(connect_fd);        return 1;    }    memset(snd_buf, 0, 1024);    strcpy(snd_buf, "message from client");    ret = write(connect_fd,snd_buf,sizeof(snd_buf));    if (ret <= 0)     {printf("write error(%d) %s\n", errno, strerror(errno));close(connect_fd);return -1;    }    close(connect_fd);    return 0;}





测试:

#./server

可通过一下命令查看结果

$ netstat -an | grep tmp/UNIX.domain
unix  2      [ ACC ]     STREAM     LISTENING     302051   /tmp/UNIX.domain




参考


http://blog.chinaunix.net/uid-26790551-id-3171897.html


http://blog.sina.com.cn/s/blog_9cd4235201019cy6.html

0 0