socket本地套接字 进程间通信 IPC

本地套接字

socket API 原本是为多台主机之间网络通信设计的,同时这种网络 socket 也支持单台主机上的进程间通信,(通过 loopback 地址 127.0.0.1)。Unix本地套接字,其实就是一种专门用于本地(也就是单个主机上的)网络通信的一种方法,它所用的 API 跟我们之前用的网络 socket API 是一样的。
  实际上,这种通信方式更类似于IPC(进程间通信)的方式,比如无名管道(pipe)、有名管道(mkfifo)。但是,Unix域套接字所提供的控制方式会更多一些,比如说TCP(字节流套接字)提 供等待连接的功能,UDP(数据报套接字)提供帧同步功能,同时也是全双工的(比如使用 socketpair 创建的流管道中的两个描述符都是既可读又可写的)。

服务器端

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<stddef.h>
#include<arpa/inet.h>
#include<sys/un.h>
#include<string.h>
#define SERV_ADDR "serv.socket"

int main(void)
{
    int lfd,cfd,len,size,i;
    struct sockaddr_un serv_addr,clie_addr;
    char buf[4096];
    lfd=socket(AF_UNIX,SOCK_STREAM,0);    //本地套接字

    bzero(&serv_addr,sizeof(serv_addr));

    serv_addr.sun_family = AF_UNIX;
    strcpy(serv_addr.sun_path,SERV_ADDR);   //路径名

    printf("offset:%ld---strlen=%ld\n",offsetof(struct sockaddr_un,sun_path),
             strlen(serv_addr.sun_path));

    len = offsetof(struct sockaddr_un,sun_path) + strlen(serv_addr.sun_path);
    /*
     * 偏移量加上路径实际长度为serv_addr结构体实际长度
     * #define offsetof(type,member) ((int)&((type *)0)->member) 宏函数
     * ((type *)0)把结构体首地址设为0,再计算偏移量,最后强转为int型
     * */
    unlink(SERV_ADDR);    //确保bind之前serv_socket不存在,bind会创建该文件

    bind(lfd,(struct sockaddr *)&serv_addr,len);

    listen(lfd,20);
    printf("Accept.......\n");
    while(1)
    {
        len=sizeof(clie_addr);
        cfd=accept(lfd,(struct sockaddr *)&clie_addr,(socklen_t *)&len);
        len-= offsetof(struct sockaddr_un,sun_path);    //得到文件名长度
        clie_addr.sun_path[len] = '\0';                 //确保打印时,没有乱码出现

        printf("client bind filename %s\n",clie_addr.sun_path);

        while((size=read(cfd,buf,sizeof(buf)))>0)
        {
            for(i=0;i<size;i++)
                buf[i]=toupper(buf[i]);
            write(cfd,buf,size);
        }
        close(cfd);
    }
} 

客户端

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<stddef.h>

#define SERV_ADDR "serv.socket"
#define CLIE_ADDR "clie.socket"

int main(void)
{
    int cfd,len;
    struct sockaddr_un serv_addr,clie_addr;
    char buf[4096];

    cfd=socket(AF_UNIX,SOCK_STREAM,0);

    bzero(&clie_addr,sizeof(clie_addr));
    clie_addr.sun_family=AF_UNIX;
    strcpy(clie_addr.sun_path,CLIE_ADDR);

    len=offsetof(struct sockaddr_un,sun_path)+strlen(clie_addr.sun_path);
    //计算客户端结构体实际大小

    unlink(CLIE_ADDR);
    bind(cfd,(struct sockaddr *)&clie_addr,len);         //客户端也需要bind,不能依赖自动绑定

    bzero(&serv_addr,sizeof(serv_addr));
    serv_addr.sun_family=AF_UNIX;
    strcpy(serv_addr.sun_path,SERV_ADDR);

    len=offsetof(struct sockaddr_un,sun_path)+ strlen(serv_addr.sun_path);  //有效长度
    connect(cfd,(struct sockaddr *)&serv_addr,len);
    printf("connect filename :%s\n",serv_addr.sun_path);
    while(1)
    {
        fgets(buf,sizeof(buf),stdin);
        write(cfd,buf,strlen(buf));
        len=read(cfd,buf,sizeof(buf));
        write(STDOUT_FILENO,buf,len);
        printf("-------------------------------------\n");
    }
    close(cfd);
}

测试结果

服务器:
在这里插入图片描述
客户端
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值