socket进程间通信

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

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


/*
IPC
socket AF_UNIX

server

*/

#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_LEN	5


int 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


/*
IPC
socket AF_UNIX

client

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

你可能感兴趣的:(socket进程间通信)