加入收藏 | 设为首页 | 会员中心 | 我要投稿 佛山站长网 (https://www.0757zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux网络编程之socket(十五) UNIX域套接字编程和socketpair 函数

发布时间:2013-09-14 20:06:57 所属栏目:Linux 来源:站长网
导读:一、UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机 制,就是UNIX Domain Socket。虽然网络socket也可用于
一、UNIX Domain Socket IPC

socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机 制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是 UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是 将应用层数据从一个进程拷贝到另一个进程。UNIX域套接字与TCP套接字相比较,在同一台主机的传输速度前者是后者的两 倍。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和 面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIXDomain Socket也是可靠的,消息既不会丢失也不会顺序错 乱。

使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符, address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。

UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP 地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用 创建,如果调用bind()时该文件已存在,则bind()错误返回。

#define UNIX_PATH_MAX    108

struct sockaddr_un {

sa_family_tsun_family;               /* AF_UNIX */

charsun_path[UNIX_PATH_MAX];  /* pathname */

};

二、回射/客户服务器程序

通信的流程跟 前面说过的tcp/udp 是类似的,下面直接来看程序:

/*************************************************************************
    > File Name: echoser_tcp.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sun 03 Mar 2013 06:13:55 PM CST
 ************************************************************************/
    
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<sys/un.h>
    
#define ERR_EXIT(m) 
    do { 
        perror(m); 
        exit(EXIT_FAILURE); 
    } while (0)
    
void echo_ser(int conn)
{
    char recvbuf[1024];
    int n;
    while (1)
    {
    
        memset(recvbuf, 0, sizeof(recvbuf));
        n = read(conn, recvbuf, sizeof(recvbuf));
        if (n == -1)
        {
            if (n == EINTR)
                continue;
    
            ERR_EXIT("read error");
        }
    
        else if (n == 0)
        {
            printf("client closen");
            break;
        }
    
        fputs(recvbuf, stdout);
        write(conn, recvbuf, strlen(recvbuf));
    }
    
    close(conn);
}
    
/* unix domain socket与TCP套接字相比较,在同一台主机的传输速度前者是后者的两倍。*/
int main(void)
{
    int listenfd;
    if ((listenfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        ERR_EXIT("socket error");
    
    unlink("/tmp/test socket"); //地址复用
    struct sockaddr_un servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, "/tmp/test socket");
    
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        ERR_EXIT("bind error");
    
    if (listen(listenfd, SOMAXCONN) < 0)
        ERR_EXIT("listen error");
    
    int conn;
    pid_t pid;
    
    while (1)
    {
    
        conn = accept(listenfd, NULL, NULL);
        if (conn == -1)
        {
    
            if (conn == EINTR)
                continue;
            ERR_EXIT("accept error");
        }
    
        pid = fork();
        if (pid == -1)
            ERR_EXIT("fork error");
        if (pid == 0)
        {
            close(listenfd);
            echo_ser(conn);
            exit(EXIT_SUCCESS);
        }
    
        close(conn);
    }
    
    return 0;
}

(编辑:佛山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读