使用TCP实现本地通信-本地通信的信息结构体sockaddr_un-传输层

使用TCP实现本地通信

在这里插入图片描述

socket

	#include <sys/types.h
	#include <sys/socket.h>

	int socket(int domain, int type, int protocol);
	
参数:
	domain:用于指定通信领域
		   AF_UNIX, AF_LOCAL	本地通信使用
			
	type:指定套接字类型
		  SOCK_STREAM			TCP协议
	
	protocol:附加协议
			  如果type使用的是  SOCK_STREAM 或者 SOCK_DGRAM
			  此时该参数可以指定为  0
返回值:
	成功  文件描述符
	失败  -1

本地通信使用的信息结构体

struct sockaddr_un {
    sa_family_t sun_family;       /* AF_UNIX */
    char        sun_path[108];    /* 带有路径的文件名 */
};

sun_path[108] 文件名,执行会自动创建 套节字文件

在这里插入图片描述

TCP本地通信流程

服务器:
		创建套接字 socket( )
		填充服务器本地信息结构体 sockaddr_un
		将套接字与服务器本地信息结构体绑定 bind( )
		将套接字设置为被动监听状态 listen( )
		阻塞等待客户端的连接请求 accept( )
		进行通信 recv( )/send( ) 
 		关闭套接字 close()
客户端:
		创建套接字 socket( )
		填充客户端本地信息结构体 sockaddr_un
		将套接字与客户端本地信息结构体绑定 bind() //客户端执行绑定,是为了服务器能获取客户端的信息;如果不绑定 服务器没法回复应答
	
		填充服务器本地信息结构体 sockaddr_un
		发送客户端的连接请求 connect( )
		进行通信 send( )/recv( )
 		关闭套接字 close()

代码实现

服务器—01server.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>

/* struct sockaddr_un */
#include <sys/socket.h>
#include <sys/un.h>

#define ERRLOG(errmsg)                                       \
    do                                                       \
    {                                                        \
        printf("%s--%s(%d):", __FILE__, __func__, __LINE__); \
        perror(errmsg);                                      \
        exit(-1);                                            \
    } while (0)

//创建套接字-填充服务器网络信息结构体-绑定-监听
int socket_bind_listen(const char *argv[]);

int main(int argc, const char *argv[])
{
    //创建套接字-填充服务器网络信息结构体-绑定-监听
    int sockfd = socket_bind_listen(argv);

    //用来保存客户端信息的结构体
    struct sockaddr_un client_addr;
    memset(&client_addr, 0, sizeof(client_addr));
    socklen_t client_addr_len = sizeof(client_addr);

    /*----------------------------------------------------------------------------*/
    //阻塞等待客户端的连接请求
    int acceptfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
    if(-1 == acceptfd)
        ERRLOG("accept error");
    
    printf("客户端[%s]连接到服务器...\n", client_addr.sun_path);
    /*----------------------------------------------------------------------------*/

    //通信
    char buff[128] = {0};
    while (1)
    {
        //接收应答
        if (-1 == recv(acceptfd, buff,sizeof(buff), 0))
            ERRLOG("recv error");
        
        printf("客户端 (%s) 发来数据:[%s]\n", client_addr.sun_path, buff);

        //组装回复给客户端的应答
        strcat(buff, "---996");
        //发送数据
        if (-1 == send(acceptfd, buff, sizeof(buff),0))
            ERRLOG("send error");
        
    }
    //关闭监听套接字  一般不关闭
    close(sockfd);

    return 0;
}

//创建套接字-填充服务器网络信息结构体-绑定
int socket_bind_listen(const char *argv[])
{
    // 1.创建套接字     /本地通信  /TCP
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (-1 == sockfd)
        ERRLOG("socket error");
    
    // 2.填充 服务器 网络信息结构体
    struct sockaddr_un server_addr;
    memset(&server_addr, 0, sizeof(server_addr));//清空
    server_addr.sun_family = AF_UNIX;            //本地通信 
    strcpy(server_addr.sun_path, "./my_local");  //套节字文件
    //结构体长度
    socklen_t server_addr_len = sizeof(server_addr);

    // 3.将套接字和网络信息结构体绑定
    if (-1 == bind(sockfd, (struct sockaddr *)&server_addr, server_addr_len))
        ERRLOG("bind error");

    /*----------------------------------------------------------------------------*/
    // 4.将套接字设置成被动监听状态
    if(-1 == listen(sockfd, 5))
        ERRLOG("listen error");
    /*----------------------------------------------------------------------------*/
    
    return sockfd;
}

客户端—02client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>

/* struct sockaddr_un */
#include <sys/socket.h>
#include <sys/un.h>

#define ERRLOG(errmsg)                                       \
    do                                                       \
    {                                                        \
        printf("%s--%s(%d):", __FILE__, __func__, __LINE__); \
        perror(errmsg);                                      \
        exit(-1);                                            \
    } while (0)

//创建套接字-填充服务器网络信息结构体-绑定
int socket_bind(const char *argv[]);

int main(int argc, const char *argv[])
{
    //创建套接字-填充服务器网络信息结构体-绑定
    int sockfd = socket_bind(argv);

    // 填充 服务器 信息结构体
    struct sockaddr_un server_addr;
    memset(&server_addr, 0, sizeof(server_addr));//清空
    server_addr.sun_family = AF_UNIX;            //本地通信 
    strcpy(server_addr.sun_path, "./my_local");  //套节字文件
    // 结构体长度
    socklen_t server_addr_len = sizeof(server_addr);

    /*----------------------------------------------------------------------------*/
    // 与服务器建立连接                           /服务器 信息结构体
    if(-1 == connect(sockfd, (struct sockaddr *)&server_addr, server_addr_len))
        ERRLOG("connect error");
    /*----------------------------------------------------------------------------*/

    //通信
    char buff[128] = {0};
    while (1)
    {
        printf("请输入 : ");
        fgets(buff,sizeof(buff), stdin);
        buff[strlen(buff) - 1] = '\0'; //清除 \n

        //发送数据
        if (-1 == send(sockfd, buff,sizeof(buff), 0))
            ERRLOG("send error");
        
        //接收应答
        if (-1 == recv(sockfd, buff,sizeof(buff), 0))
            ERRLOG("recv error");
        
        printf("服务器应答[%s]\n", buff);
    }
    //关闭监听套接字  一般不关闭
    close(sockfd);

    return 0;
}

//创建套接字-填充服务器网络信息结构体-绑定
int socket_bind(const char *argv[])
{
    // 1.创建套接字     /本地通信  /TCP
    int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (-1 == sockfd)
        ERRLOG("socket error");

    //2.填充 客户端自己 网络信息结构体
    struct sockaddr_un client_addr;
    memset(&client_addr, 0, sizeof(client_addr));  //清空
    client_addr.sun_family = AF_UNIX;              //本地通信 
    strcpy(client_addr.sun_path, "./my_local_cli");//套节字文件
    socklen_t client_addr_len = sizeof(client_addr);

    // 3.将套接字和本地信息结构体绑定(客户端)
    if (-1 == bind(sockfd, (struct sockaddr *)&client_addr, client_addr_len))
        ERRLOG("bind error");
    
    return sockfd;
}

执行结果

在这里插入图片描述
在这里插入图片描述

注意

1. 客户端侧,不仅 要将 自己的信息 结构体 与 sockfd套接字 绑定 ;还得 填充 服务器信息 信息结构体

填充 服务器信息 信息结构体 :以便于与服务器建立连接
connect(sockfd, (struct sockaddr *)&server_addr, server_addr_len)

2. 报错 :bind error: Address already in use
因为已经执行一次 套节字文件 已经存在
所以 只需要删除 套节字文件 即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值