IPC之本地套接字

IPC之本地套接字

 

    进程间通信,UNP2 这本经典的书籍讲的已经很清楚了,常见的进程间通信就是信号量 消息队列共享内存,其实本地套接字更是一种进程间通信的手段,而且起码要比信号量更加直观。本文描述下基本的利用本地套接字来进行进程通信。

点击(此处)折叠或打开

#define UNIX_PATH_MAX 108

 

struct sockaddr_un {

       sa_family_tsun_family; /* AF_UNIX */

       charsun_path[UNIX_PATH_MAX]; /* pathname */

};

                   

    可以看到这就是本地套接字的数据结构,110个字节,sun_path相当于socket的门牌号,或者地址,用于通信。我们知道,两个人通信,如果你知道对方的门牌号,那么你就能找到他,和他聊天。本地套接字也是一样,如果我是服务器,就在我门牌号这里等待别人来找我。

 

    

 

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<errno.h>

#include<string.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<sys/socket.h>

#include<sys/un.h>

#include<signal.h>

 

int pipe_process()

{

        structsigaction newact,oldact;

        newact.sa_handler = SIG_IGN;

        sigemptyset(&newact.sa_mask);

        newact.sa_flags = 0;

        

        sigaction(SIGPIPE,&newact,&oldact);

        return0;

}



int main()

{

                int server_sockfd,client_sockfd;

                int server_len,client_len;

                structsockaddr_un server_address;

                structsockaddr_un client_address;

                const charpath_unix[] = "MY_SOCKET";

                int len_unix;

                charbuf[1024];

                int n;

 

                unlink("MY_SOCKET");

                server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

 

                server_address.sun_family = AF_UNIX;

                strncpy(server_address.sun_path, path_unix,sizeof(server_address.sun_path));

                server_len = sizeof(server_address);

                len_unix = SUN_LEN(&server_address);

                bind(server_sockfd,(structsockaddr *)&server_address,server_len);

               

               pipe_process();

                listen(server_sockfd, 5);

                while(1){

 

                               printf("server waiting\n");

  

                                client_len = sizeof(client_address);

                                client_sockfd = accept(server_sockfd,(structsockaddr *)&client_address, &client_len);

                

                                memset(buf,0,sizeof(buf)/sizeof(buf[0]));

                                n = read(client_sockfd,buf,1024);

                             if(n < 0)

                                {

                                fprintf(stderr,"read failed\n");

                                        return -1;

                                }

                                fprintf(stderr,"recv: %s\n",buf);

                                close(client_sockfd);

                }

}

 

     我们看下这几行代码

       const charpath_unix[] = "MY_SOCKET";

       unlink("MY_SOCKET");

       server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

 

       server_address.sun_family = AF_UNIX;

       strncpy(server_address.sun_path, path_unix,sizeof(server_address.sun_path));

       server_len = sizeof(server_address);

       len_unix = SUN_LEN(&server_address);

       bind(server_sockfd,(struct sockaddr *)&server_address,server_len);

 

    我先定义了一个门牌号,然后将我的套接字和门牌号绑定,这样的话,别人就能通过我的门牌号找到我了。这里插一段,SUN_LEN是一个宏来告知sockaddr_un的有效长度,对于本例子,len_unix = 2 + 9 =11.

 

 

     我们看到我们的套接字有了门牌号,这样客户端想要连接的话,就可以根据门牌号,按图索骥的找到我们了。

 

    下面是客户端的代码:

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/un.h>

#defineUNIX_DOMAIN "MY_SOCKET"

 

int main(void)

{

                int connect_fd;

                int ret;

                charsnd_buf[1024];

                int i;

                staticstruct sockaddr_un srv_addr;

                

                connect_fd=socket(PF_UNIX,SOCK_STREAM,0);

                if(connect_fd<0)

                {

                                fprintf(stderr,"cannotcreate communication socket");

                                return1;

                } 

                srv_addr.sun_family=AF_UNIX;

                strcpy(srv_addr.sun_path,UNIX_DOMAIN);

                

                ret=connect(connect_fd,(structsockaddr*)&srv_addr,sizeof(srv_addr));

                if(ret==-1)

                {

                                perror("cannotconnect to the server");

                                close(connect_fd);

                                return1;

                }

                memset(snd_buf,0,1024);

                strcpy(snd_buf,"helloserver !");

                

                write(connect_fd,snd_buf,sizeof(snd_buf));

                close(connect_fd);

                return0;

}

    可以看到,关键部分就是加粗的那部分代码,客户端根据sun_path就能找到服务器,然后去连接服务器。我们看到客户端给服务器进程发了个helloserver就退出了。实际工程代码中,可以发送双方约定好的很复杂的数据,告诉服务器进程去处理客户端进程提交的数据。

 

    OK,看下效果:

    先启动服务器进程,可以看到服务器在等待客户来连接。

 

root@libin:~/program/C/sock/af_unix#./server

server waiting

    然后启动客户端进程,客户段打了招呼就退出了,

 

root@libin:~/program/C/sock/af_unix#./client

root@libin:~/program/C/sock/af_unix#

   看下服务器的反应:服务器的确是收到了发来的语句,同时继续等待。

 

recv : hello server !

server waiting

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值