zoukankan      html  css  js  c++  java
  • 使用C语言实现本地socke通讯

    一、概述

      使用本地socket通讯可以实现进程之间的通讯。

      相关函数描述如下:

    int socket(int domain, int type, int protocol);
    函数说明: 创建本地域socket
    函数参数:    
        domain: AF_UNIX or AF_LOCAL
        type: SOCK_STREAM或者SOCK_DGRAM
        protocol: 0 表示使用默认协议
    函数返回值:
        成功: 返回文件描述符.
        失败: 返回-1, 并设置errno值.
    
    创建socket成功以后, 会在内核创建缓冲区, 下图是客户端和服务端内核缓冲区示意图.
    
    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    函数说明: 绑定套接字
    函数参数:
        socket: 由socket函数返回的文件描述符
        addr: 本地地址
        addlen: 本地地址长度
    函数返回值:
        成功: 返回文件描述符.
        失败: 返回-1, 并设置errno值.
    
    需要注意的是: bind函数会自动创建socket文件, 若在调用bind函数之前socket文件已经存在, 则调用bind会报错, 可以使用unlink函数在bind之前先删除文件.
    struct sockaddr_un {
        sa_family_t sun_family;  /* AF_UNIX or AF_LOCAL*/
        char sun_path[108];  /* pathname */
    };

      整体使用步骤和网络通讯的socket是差不多的,如下所示:

    tcp的本地套接字服务器流程:
        创建套接字  socket(AF_UNIX,SOCK_STREAM,0)
        绑定 struct sockaddr_un &强转
        侦听 listen 
        获得新连接 accept 
        循环通信 read-write 
        关闭文件描述符 close
    
    tcp本地套接字客户端流程:
        调用socket创建套接字
        调用bind函数将socket文件描述和socket文件进行绑定.
            不是必须的, 若无显示绑定会进行隐式绑定,但服务器不知道谁连接了.
        调用connect函数连接服务端
        循环通信read-write
        关闭文件描述符 close

    二、代码示例

      1.服务端代码示例

    //本地socket通讯服务端
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/un.h>
    
    int main(){
        //创建socket
        int lfd = socket(AF_UNIX,SOCK_STREAM,0);
        if(lfd<0){
            perror("socket error");
            return -1;
        }
    
        //删除socket文件,避免bind失败
        unlink("./server.sock");
    
        //绑定
        struct sockaddr_un serv;
        bzero(&serv,sizeof(serv));
        serv.sun_family = AF_UNIX;
        strcpy(serv.sun_path,"./server.sock");
        int ret = bind(lfd,(struct sockaddr *)&serv,sizeof(serv));
        if(ret<0){
            perror("bind error");
            return -1;
        }
        //监听
        listen(lfd,10);
        //接收新的链接-accept
        struct sockaddr_un client;
        bzero(&client,sizeof(client));
        socklen_t len = sizeof(client);
        int cfd = accept(lfd,(struct sockaddr*)&client,&len);
        if(cfd<0){
            perror("accept error");
            return -1;
        }
    
        printf("cient->[%s]\n",client.sun_path);
    
        int n;
        char buf[1024];
        while(1){
            //读取数据
            memset(buf,0x00,sizeof(buf));
            n = read(cfd,buf,sizeof(buf));
            if(n<=0){
                printf("read error or client close ,n=[%d]\n",n);
                break;
            }
            printf("n=[%d],buf=[%s]\n",n,buf);
            //发送数据
            write(cfd,buf,n);
    
        }
        //关闭套接字
        close(lfd);
        return 0;
    }

      2.客户端代码示例

    //本地socket通信客户端
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/un.h>
    
    
    int main(){
        //创建socket
        int cfd = socket(AF_UNIX,SOCK_STREAM,0);
        if(cfd<0){
            perror("socket error");
            return -1;
        }
        //删除socket文件,避免bind失败
        unlink("./client.sock");
        //绑定
        struct sockaddr_un client;
        bzero(&client,sizeof(client));
        client.sun_family= AF_UNIX;
        strcpy(client.sun_path,"./client.sock");
        int ret = bind(cfd,(struct sockaddr*)&client,sizeof(client));
        if(ret<0){
            perror("bind error");
            return -1;
        }
        struct sockaddr_un serv;
        bzero(&serv,sizeof(serv));
        serv.sun_family = AF_UNIX;
        strcpy(serv.sun_path,"./server.sock");
        ret = connect(cfd,(struct sockaddr*)&serv,sizeof(serv));
        if(ret<0){
            perror("connect error");
            return -1;
        }
    
        int n;
        char buf[1024];
        while(1){
            memset(buf,0x00,sizeof(buf));
            n = read(STDIN_FILENO,buf,sizeof(buf));
    
            //发送数据
            write(cfd,buf,n);
    
            //读取数据
            memset(buf,0x00,sizeof(buf));
            n = read(cfd,buf,sizeof(buf));
            if(n<=0){
                printf("read error or client close ,n=[%d]",n);
                break;
            }
            printf("n=[%d],buf=[%s]",n,buf);
    
        }
        close(cfd);
        return 0;
    }
  • 相关阅读:
    1112评论
    1029 C语言文法
    0909编译原理理解和解释
    复利计算4.0-单元测试
    命令解析程序的编写
    《构建之法》1、2、3章思考与感想
    复利计算4.0
    实验三的分析与总结
    复利计算(更新)
    单、复利计算程序
  • 原文地址:https://www.cnblogs.com/tony-yang-flutter/p/15709973.html
Copyright © 2011-2022 走看看