《UNIX环境高级编程》笔记--UNIX域套接字

1.非命名的UNIX域套接字

UNIX套接字用于在用一台机器上运行的进程之间通信。UNIX套接字比因特网域套接字的效率更高。UNIX与套接字提供和

数据报两种接口,UNIX域数据报服务是可靠的,就不会丢失消息也不会传递出错。UNIX域套接字是套接字和管道之间的混合物。

为了创建一对非命名的,相互连接的UNXI域套接字,用户可以使用socketopair函数。

#include<sys/socket.h>
int socketpari(int domain, int type, int protocol, int sockfd[2]); //若成功则返回0,出错则返回-1.
实践:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>

int main(void){
        int fd[2];
        int pid;
        char wbuf[16] = "1234567890";
        char rbuf[16];
        if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){
                perror("socketpair");
                return -1;
        }

        if((pid = fork())<0){
                perror("fork");
                return -1;
        }else if(pid == 0){
                //child
                close(fd[0]);
                if(write(fd[1],wbuf,strlen(wbuf)) < 0){
                        perror("write");
                        exit(-1);
                }
        }else{
                //parent
                close(fd[1]);
                if(read(fd[0],rbuf,16) < 0){
                        perror("read");
                        exit(-1);
                }
                printf("%s\n",rbuf);
        }
        return 0;
}
执行结果:

yan@yan-vm:~$ ./a.out
1234567890


2.命名UNIX域套接字

虽然socketpair函数创建相互连接的一对套接字,但是每一个套接字都没有名字。这意味着无关进程不能使用它们。

我们可以命名unix域套接字,并可将其用于告示服务。但是要注意的是,UNXI与套接字使用的地址不同与因特网域套接字。

UNIX域套接字的地址由sockaddr_un结构表示。

在linux2.4.22中,sockaddr_un结构按下列形式定义在有文件<sys/un.h>中。

struct sockaddr_un{

sa_family_t sun_family; //AF_UNIX

char sun_path[108]; //pathname

};

sun_path成员包含一路经名,当我们将一个地址绑定至UNIX域套接字时,系统用该路经名创建一类型为S_IFSOCK文件。

该文件仅用于向客户进程告知套接字名字。该文件不能打开,也不能由应用程序用于通信。

如果当我们试图绑定地址时,该文件已经存在,那么bind请求失败。当关闭套接字时,并不自动删除该文件,所以我们必须

确保在应用程序终止前,对该文件执行解除链接操作。

服务器进程可以使用标准bind、listen和accept函数,为客户进程安排一个唯一UNIX域连接。客户进程使用connect与服务器

进程连接;服务器进程接受了connect请求后,在服务器进程和客户进程之间就存在了唯一连接。这种风格和因特网套接字

的操作很像。

实践:

server.c

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>

int main(void){
        int fd,clientfd;
        int client_addr_len = sizeof(struct sockaddr_un);
        struct sockaddr_un un,clientun;
        char path[32]="serversocketfile";
        int addr_len = sizeof(struct sockaddr_un);
        char rbuf[32];
        char wbuf[32] = "i am server.";

        //create a UNIX domain stream socket
        if((fd = socket(AF_UNIX,SOCK_STREAM,0)) < 0){
                perror("socket");
                return -1;
        }

        //in case it already exists
        unlink(path);

        //fill in socket address structure
        memset(&un, 0, sizeof(un));
        un.sun_family = AF_UNIX;
        strncpy(un.sun_path,path,32);

        //bind the name to the descriptor
        if(bind(fd, (struct sockaddr*)&un, addr_len) < 0){
                perror("bind");
                return -1;
        }

        if(listen(fd, 10) < 0){
                perror("listen");
                return -1;
        }

        if((clientfd = accept(fd,(struct sockaddr*)&clientun,(socklen_t*)&client_addr_len)) < 0 ){
                perror("accept");
                return -1;
        }

        printf("client is:%s\n",clientun.sun_path);

        if(read(clientfd,rbuf,32) < 0){
                perror("read");
                return -1;
        }
        printf("receive msg:%s\n",rbuf);

        if(write(clientfd,wbuf,strlen(wbuf)+1) < 0){
                perror("write");
                return -1;
        }

        unlink(path);
        return 0;
}

client.c

#include <stdio.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <string.h>

int main(void){
        int fd;
        struct sockaddr_un un;
        char path[32] = "clientsocketfile";
        char serverpath[32] = "serversocketfile";
        int addr_len = sizeof(struct sockaddr_un);
        char wbuf[32] = "i am client.";
        char rbuf[32];

        if((fd = socket(AF_UNIX,SOCK_STREAM,0))<0){
                perror("socket");
                return -1;
        }

        memset(&un,0,sizeof(un));
        un.sun_family = AF_UNIX;
        strncpy(un.sun_path,path,32);
        unlink(path);

        if(bind(fd,(struct sockaddr*)&un,addr_len)<0){
                perror("bind");
                return -1;
        }

        //fill socket adress structure with server's address
        memset(&un,0,sizeof(un));
        un.sun_family = AF_UNIX;
        strncpy(un.sun_path,serverpath,32);

        if(connect(fd,(struct sockaddr*)&un,addr_len) < 0){
                perror("connect");
                return -1;
        }

        if(write(fd,wbuf,strlen(wbuf)+1)<0){
                perror("write");
                return -1;
        }

        if(read(fd,rbuf,32) < 0){
                perror("write");
                return -1;
        }
        printf("receive msg:%s\n",rbuf);
        unlink(path);
        return -1;
}

先运行server,再运行client。

运行结果:

server.c:

yan@yan-vm:~/apue$ ./unixserver
client is:clientsocketfile
receive msg:i am client.

client.c:

yan@yan-vm:~/apue$ ./unixclient
receive msg:i am server.

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值