socket进程间通信

转自 http://blog.youkuaiyun.com/lanyang123456/article/details/40299623

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


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


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

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




而in_addr被定义为:

  1. <span style="font-size:14px;">struct in_addr{    
  2.     unsigned long int s_addr;    
  3. };  </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


  1. /* 
  2. IPC 
  3. socket AF_UNIX 
  4.  
  5. server 
  6.  
  7. */  
  8.   
  9. #include <stdio.h>  
  10. #include <sys/types.h>  
  11. #include <sys/socket.h>  
  12. #include <sys/un.h>   
  13. #include <errno.h>  
  14.   
  15. #define UNIX_DOMAIN "/tmp/UNIX.domain"  
  16. #define QUEUE_LEN   5  
  17.   
  18.   
  19. int main(void)  
  20. {  
  21.     socklen_t clt_addr_len;  
  22.     int listen_fd;  
  23.     int com_fd;  
  24.     int ret;  
  25.     int i;  
  26.     char recv_buf[1024];   
  27.     int len;  
  28.     struct sockaddr_un client_addr;  
  29.     struct sockaddr_un server_addr;  
  30.   
  31.     listen_fd=socket(PF_UNIX, SOCK_STREAM, 0);  
  32.     if(listen_fd < 0)  
  33.     {  
  34.         perror("cannot create communication socket");  
  35.         return -1;  
  36.     }    
  37.       
  38.     //set server addr  
  39.     server_addr.sun_family = AF_UNIX;  
  40.     strncpy(server_addr.sun_path, UNIX_DOMAIN, sizeof(server_addr.sun_path) - 1);  
  41.     unlink(UNIX_DOMAIN);  
  42.   
  43.     //bind sockfd & addr  
  44.     ret = bind(listen_fd, (struct sockaddr*)&server_addr,sizeof(server_addr));  
  45.     if(ret == -1)  
  46.     {  
  47.         perror("cannot bind server socket");  
  48.         close(listen_fd);  
  49.         unlink(UNIX_DOMAIN);  
  50.         return -1;  
  51.     }  
  52.   
  53.     //listen sockfd   
  54.     ret = listen(listen_fd, 1);  
  55.     if(ret==-1)  
  56.     {  
  57.         perror("cannot listen the client connect request");  
  58.         close(listen_fd);  
  59.         unlink(UNIX_DOMAIN);  
  60.         return -1;  
  61.     }  
  62.   
  63.     //have connect request use accept  
  64.     len = sizeof(client_addr);  
  65.     com_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len);  
  66.     if(com_fd < 0)  
  67.     {  
  68.         perror("cannot accept client connect request");  
  69.         close(listen_fd);  
  70.         unlink(UNIX_DOMAIN);  
  71.         return -1;  
  72.     }  
  73.   
  74.     //read and printf sent client info  
  75.     printf("---------------\n");  
  76.     
  77.     memset(recv_buf,0,1024);  
  78.     ret = read(com_fd, recv_buf, sizeof(recv_buf) - 1);  
  79.     if (ret <= 0)   
  80.     {  
  81.     printf("write error(%d) %s\n", errno, strerror(errno));  
  82.     close(com_fd);  
  83.         close(listen_fd);  
  84.         unlink(UNIX_DOMAIN);  
  85.         return -1;  
  86.     }  
  87.   
  88.     printf("Message from client :%s\n", recv_buf);    
  89.   
  90.     close(com_fd);  
  91.     close(listen_fd);  
  92.     unlink(UNIX_DOMAIN);  
  93.     return 0;  
  94. }  


client


  1. /* 
  2. IPC 
  3. socket AF_UNIX 
  4.  
  5. client 
  6.  
  7. */  
  8. #include <stdio.h>  
  9. #include <sys/types.h>  
  10. #include <sys/socket.h>  
  11. #include <sys/un.h>  
  12. #include <errno.h>  
  13.   
  14. #define UNIX_DOMAIN "/tmp/UNIX.domain"  
  15.   
  16.   
  17. int main(void)  
  18. {  
  19.     int connect_fd;  
  20.     int ret;  
  21.     char snd_buf[1024];  
  22.     int i;  
  23.     static struct sockaddr_un server_addr;  
  24.   
  25.     //creat unix socket  
  26.     connect_fd=socket(AF_UNIX, SOCK_STREAM, 0);  
  27.     if(connect_fd<0)  
  28.     {  
  29.         perror("cannot create communication socket");  
  30.         return 1;  
  31.     }  
  32.   
  33.     server_addr.sun_family = AF_UNIX;  
  34.     strcpy(server_addr.sun_path, UNIX_DOMAIN);  
  35.     //connect server  
  36.     ret=connect(connect_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));  
  37.     if(ret==-1)  
  38.     {  
  39.         perror("cannot connect to the server");  
  40.         close(connect_fd);  
  41.         return 1;  
  42.     }  
  43.   
  44.     memset(snd_buf, 0, 1024);  
  45.     strcpy(snd_buf, "message from client");  
  46.   
  47.     ret = write(connect_fd,snd_buf,sizeof(snd_buf));  
  48.     if (ret <= 0)   
  49.     {  
  50.     printf("write error(%d) %s\n", errno, strerror(errno));  
  51.     close(connect_fd);  
  52.     return -1;  
  53.     }  
  54.   
  55.     close(connect_fd);  
  56.     return 0;  
  57. }  





测试:

#./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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值