C语言---Unix套接字用于本地通信

1、作用:用于本地间通信

2、使用:

        创建套接字的时候使用本地协议通信,AF_UNIX(或者AF_LOCAL),分为流式套接字和用户数据报套接字。

unix_socket = socket(AF_LOCAL, SOCK_STREAM, 0);
unix_socket = socket(AF_LOCAL, SOCK_DGRAM, 0);

3、进程间通信:(6种情况)

        3.1进程间数据共享:

                管道、消息队列、共享内存、unix套接字

                        易用性:消息队列>unix套接字>管道>共享内存(经常要和信号量一起用)

                        效率上:共享内存>unix套接字>管道>消息队列

                        共享内存相当于把一块内存从内核空间放到内存空间去操作。

                        效率上,常常共享内存和信号量一起使用,或者unix套接字。

        3.2异步通信:

                信号

        3.3同步和互斥:

                信号量       

4、Unix域套接字

/*本地地址结构*/

#include <sys/un.h>
strcut sockaddr_in{
    sa_family_t sun_family; 
    char sun_path[108];  //套接字文件的路径
};

/*填充地址结构*/
strcut sockaddr_un myaddr;
bzero(&myaddr, sizeof(myaddr));
myaddr.sun_family = AF_UNIX;
strcpy(myaddr.sun_path, "/tmp/mysock");

5、

        5.1流式套接字服务器端

                socket(AF_UNIX, SOCK_STREAM, 0);

                bind(,本地地址,); //

                listen();

                accept();    //可以使用多路复用、多进程、多线程处理

                recv()  / send()

                close()

                注意:bind()函数详解

                        int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

                        之前互联网通信,这里绑定绑定的是通用地址结构体sockaddr。

                        现在本地通信,绑定的是sockaddr_un结构体,格式如下:     

//A UNIX domain socket address is represented in the following structure:

#define UNIX_PATH_MAX    108

struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[UNIX_PATH_MAX];  /* pathname */
};

//sun_family always contains AF_UNIX  / AF_local
// unix_path_max  从96~108,是unix域套接字的文件路径名:
// 注意:1.这个文件(位于内存中)必须事先不存在;2.一般给绝对路径名;

        5.2流式套接字客户端  

                socket(AF_UNIX, SOCK_STREAM, 0);

                bind(,本地地址,); //

                listen();

                accept();    //可以使用多路复用、多进程、多线程处理

                recv()  / send()

                close()

6、实例代码

/*服务器:*/
void sig_child_handle(int signo){
    if(SIGCHLD == signo){
        //NULL:状态不许要,WNOHANG非阻塞方式
        waitpid(-1, NULL, WNOHANG);
    }   
}

void cli_data_handle(int *arg);

int main(int argc, char *argv[])
{
    //1.create socket
    int sockfd;
    //struct sockaddr_in sin;
    /*  
        typedef void (*sighandler_t)(int);
        sighandler_t signal(int signum, sighandler_t handler);
    */
 signal(SIGCHLD, sig_child_handle);

    if((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0))<0){
        perror("create socket");
        return -1;
    }

struct sockaddr_un sun;
    bzero(&sun, sizeof(sun));
    sun.sun_family = AF_UNIX;

    if(!access(UNIX_DOMAIN_FILE, F_OK)){
        unlink(UNIX_DOMAIN_FILE);
    }

    strncpy(sun.sun_path, UNIX_DOMAIN_FILE, strlen(UNIX_DOMAIN_FILE));

    if( ( bind(sockfd, (struct sockaddr *)(&sun), sizeof(sun)) ) == -1){
        perror("bind");
        exit(1);
    }
//3.listen
    if(listen(sockfd, BACKLOG)<0){
        perror("listen");
        exit(1);
    }
    printf("server start\n");

 int newfd;
    while(1){
        pid_t pid = -1;
        if((newfd = accept(sockfd, NULL, NULL))<0){
            perror("accept");
            break;
        }
        //创建一个子进程,用于处理连接的客户端的交互数据
        if((pid = fork()) < 0){
            perror("fork");
            exit(1);
        }
        if(pid > 0){//父进程
            close(newfd);
        }else if(pid == 0){//子进程
            close(sockfd);
            cli_data_handle(&newfd);
            exit(1);
        }
        break;
    }
    //6.close
    close(sockfd);
    return 0;
}
void cli_data_handle(int *arg){
    int newfd = *(int *)arg;
    printf("child handling process:newfd=%d\n", newfd);
    //5.write() 与newfd读写数据
    char buf[128];
    //char resp_buf[138];
    int ret = -1;
    while(1){
        bzero(buf, strlen(buf));
        do{
            ret = read(newfd, buf, 127);
        }while(ret<0 && errno==EINTR);

        if(ret < 0){
            perror("read");
            exit(1);
        }
        //客户端已经关闭
        if(!ret){
            break;
        }
        printf("recive data:%s\n", buf);

        if( !strncasecmp(buf, QUIT_STR, strlen(QUIT_STR)) ){

            printf("client(%d) exiting\n", newfd);
            break;
        }
    }
    close(newfd);
}
                    

                

/*./client unix_domain_file */
#include "inet.h"

void usage(char *s){
    printf("\n%s unix_domain_file\n", s); 
}

int main(int argc, char *argv[])
{   

    if(argc != 2){ 
        usage(argv[0]);
        exit(1);
    }   
    //1.create socket
    int sockfd;
    if((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0))<0){
        perror("create socket");
        exit(1);
    }   
//2.连接服务器
    //填充sockaddr_in 结构体变量,

    struct sockaddr_un sun;
    bzero(&sun, sizeof(sun));

    sun.sun_family = AF_LOCAL;

    /*确保文件先存在并且可写,如果不存在,退出*/
    if(access(UNIX_DOMAIN_FILE, W_OK) < 0){
        exit(1);
    }

    strncpy(sun.sun_path, UNIX_DOMAIN_FILE, strlen(UNIX_DOMAIN_FILE));

    if(connect(sockfd, (struct sockaddr *)&sun, sizeof(sun)) < 0){
        perror("connect");
        exit(1);
    }
    printf("unix start....\n");
 //3.read()读写数据
    int ret = -1;
    char buf[128];
    while(1){
        bzero(buf, 128);
        if(fgets(buf, 127, stdin) == NULL){
            continue;
        }
        do{
            ret = write(sockfd, buf, strlen(buf));
        }while(ret<0 && errno==EINTR);
        if(! strncasecmp(buf, QUIT_STR, strlen(buf)-1)){
            printf("client is exiting\n");
            break;
        }
    }
    //4.close()关闭套接字
    close(sockfd);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值