linux本地套接字--tcp,udp实现

本地套接字顾名思义就是用于本地通信的套接字,虽然网络套接字也能用于本地通信(通过本地回环测试127.0.0.1),但是还是需要绑定IP地址和端口号,这就没有本地套接字通信那么简便了。但是需要注意的事在客户端需要建立两个地址结构, 一个是定义自己的,一个是标注目的服务端的,而且是绝对路径,这样在服务端接收数据的时候就知道是哪个客户端伪文件传来的,不然的话打印不出来绝对路径。bind创建出来的文件就是伪文件(套接字文件),这个文件的大小是0,可以说就是一个棋子。

/虽然在很多教材中经常把Unix本地套接字放在网络编程里面进行讲解,但实际上,这种通信方式更类似于我们之前所学的IPC(进程间通信)的方式,比如无名管道(pipe)、有名管道(mkfifo)。但是,Unix域套接字所提供的控制方式会更多一些,比如说TCP(字节流套接字)提供等待连接的功能,UDP(数据报套接字)提供帧同步功能,同时也是全双工的(比如使用 socketpair 创建的流管道中的两个描述符都是既可读又可写的)。/转载一段文字

TCP服务端代码:

/*************************************************************************
	> File Name: tcp_server.c
	> Author: chencj
	> Mail: 1378755306@qq.com 
	> Created Time: 2020年08月15日 星期六 14时58分47秒
 ************************************************************************/

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

#define FILE_PATH "/tmp/server.txt"   //最好用绝对路径

void sys_err(const char *msg)
{
    perror(msg);
    exit(1);
}
int main()
{
    int lfd,cfd;
    char buf[128];
    lfd = socket(AF_LOCAL,SOCK_STREAM,0);
    if(lfd == -1)
        sys_err("socket error\n");

    struct sockaddr_un server_addr,client_addr;   //地址结构
    server_addr.sun_family = AF_LOCAL;
    strcpy(server_addr.sun_path,FILE_PATH);
    
    unlink(FILE_PATH);
    //bind会在绝对路径下创建一个套接字伪文件,创建之前清除该文件
    if(bind(lfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)

        sys_err("bind error\n");
    if(listen(lfd,128) == -1)
        sys_err("listen error\n");

    //只与一个客户端进行通信
    socklen_t len = sizeof(client_addr);
    cfd = accept(lfd,(struct sockaddr*)&client_addr,&len);
    if(cfd == -1)
        sys_err("accept error\n");

    while(1)
    {
        bzero(buf,sizeof(buf));
        int recvb = read(cfd,buf,sizeof(buf));
        if(recvb == 0) {
            printf("client disconnect...\n");
            close(cfd);
            break;
        }
        printf("file path %s : %s\n",client_addr.sun_path,buf);
        write(cfd,"accept",7);
    }
    close(lfd);
    return 0;
}

TCP客户端代码:

/*************************************************************************
	> File Name: tcp_client.c
	> Author: chencj
	> Mail: 1378755306@qq.com 
	> Created Time: 2020年08月15日 星期六 15时14分36秒
 ************************************************************************/

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

#define CLI_FILE_PATH "/tmp/client.txt"
#define SRV_FILE_PAYH "/tmp/server.txt"

void sys_err(const char *msg)
{
    perror(msg);
    exit(1);
}
int main()
{
    char buf[128];
    int sockfd;
    sockfd = socket(AF_LOCAL,SOCK_STREAM,0);
    if(sockfd == -1)
        sys_err("socket error\n");

    struct sockaddr_un server_addr,client_addr;
    client_addr.sun_family = AF_LOCAL;
    strcpy(client_addr.sun_path,CLI_FILE_PATH);
    //不能像网络套接字那样隐式绑定
    //客户端也要建立一个套接字伪文件,这样服务器在接受数据的时候才知道是本地的哪个路径下发来的
    unlink(CLI_FILE_PATH);
    bind(sockfd,(struct sockaddr*)&client_addr,sizeof(client_addr));

    //目的服务器的地址结构
    server_addr.sun_family = AF_LOCAL;
    strcpy(server_addr.sun_path,SRV_FILE_PAYH);
    //connect;
    if(connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)  //与目的服务器进行连接
        sys_err("connect error\n");

    bzero(buf,sizeof(buf));

    while(fgets(buf,128,stdin) != NULL)
    {
        write(sockfd,buf,sizeof(buf));
        bzero(buf,sizeof(buf));
        read(sockfd,buf,sizeof(buf));
        printf("recv from server : %s\n",buf);
        bzero(buf,sizeof(buf));
    }
    close(sockfd);
    return 0;
}

UDP服务端代码:

/*************************************************************************
	> File Name: tcp_server.c
	> Author: chencj
	> Mail: 1378755306@qq.com 
	> Created Time: 2020年08月15日 星期六 14时58分47秒
 ************************************************************************/

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

#define FILE_PATH "/tmp/server.txt"   //最好用绝对路径

void sys_err(const char *msg)
{
    perror(msg);
    exit(1);
}
int main()
{
    int sockfd;
    char buf[128];
    sockfd = socket(AF_LOCAL,SOCK_DGRAM,0);
    if(sockfd == -1)
        sys_err("socket error\n");

    struct sockaddr_un server_addr,client_addr;   //地址结构
    bzero(&client_addr,sizeof(client_addr));
    server_addr.sun_family = AF_LOCAL;
    strcpy(server_addr.sun_path,FILE_PATH);
    
    unlink(FILE_PATH);
    //bind会在绝对路径下创建一个套接字伪文件,创建之前清除该文件
    if(bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
        sys_err("bind error\n");

    socklen_t len = sizeof(client_addr);
    while(1)
    {
        bzero(buf,sizeof(buf));
        int recvb;
        recvb = recvfrom(sockfd,buf,128,0,(struct sockaddr *)&client_addr,&len);
        if(recvb == -1)
            sys_err("recvfrom error\n");

        printf("file path %s : %s\n",client_addr.sun_path,buf);
        sendto(sockfd,"accept",128,0,(struct sockaddr *)&client_addr,len);
    }
    close(sockfd);
    return 0;
}

UDP客户端代码:

/*************************************************************************
	> File Name: tcp_client.c
	> Author: chencj
	> Mail: 1378755306@qq.com 
	> Created Time: 2020年08月15日 星期六 15时14分36秒
 ************************************************************************/

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

#define CLI_FILE_PATH "/tmp/client.txt"
#define SRV_FILE_PAYH "/tmp/server.txt"

void sys_err(const char *msg)
{
    perror(msg);
    exit(1);
}
int main()
{
    char buf[128];
    int sockfd;
    sockfd = socket(AF_LOCAL,SOCK_DGRAM,0);
    if(sockfd == -1)
        sys_err("socket error\n");

    struct sockaddr_un server_addr,client_addr;
    client_addr.sun_family = AF_LOCAL;
    strcpy(client_addr.sun_path,CLI_FILE_PATH);
    //不能像网络套接字那样隐式绑定
    //客户端也要建立一个套接字伪文件,这样服务器在接受数据的时候才知道是本地的哪个路径下发来的
    unlink(CLI_FILE_PATH);
    bind(sockfd,(struct sockaddr*)&client_addr,sizeof(client_addr));

    //目的服务器的地址结构
    server_addr.sun_family = AF_LOCAL;
    strcpy(server_addr.sun_path,SRV_FILE_PAYH);

    bzero(buf,sizeof(buf));
    struct sockaddr_un recvaddr;
    socklen_t len = sizeof(recvaddr);
    bzero(&recvaddr,len);
    while(fgets(buf,128,stdin) != NULL)
    {
        sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&server_addr,sizeof(server_addr));
        bzero(buf,sizeof(buf));
        recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&recvaddr,&len);
        printf("recvform server : %s\n",buf);
        bzero(buf,sizeof(buf));
    }
    close(sockfd);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

译制片~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值