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

  • Post author:
  • Post category:其他




使用UDP实现本地通信

在这里插入图片描述



socket

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

	int socket(int domain, int type, int protocol);
	
参数:
	domain:用于指定通信领域
		   AF_UNIX, AF_LOCAL	本地通信使用
			
	type:指定套接字类型
		  SOCK_DGRAM			UDP协议
	
	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] 文件名,执行会

自动创建

套节字文件

在这里插入图片描述



UDP本地通信流程

服务器:
		创建套接字 socket( )
		填充服务器本地信息结构体 sockaddr_un
		将套接字与服务器本地信息结构体绑定 bind( )
		进行通信 recvfrom( ) / sendto( )	
客户端:
		创建套接字 socket( )
		填充客户端本地信息结构体 sockaddr_un
		将套接字与客户端本地信息结构体绑定 bind() //客户端执行绑定,是为了服务器能获取客户端的信息;如果不绑定 服务器没法回复应答
		填充服务器本地信息结构体 sockaddr_un
		进行通信 sendto( ) / recvfrom( )



代码实现



服务器—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(const char *argv[]);

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

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

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

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

    return 0;
}

//创建套接字-填充服务器网络信息结构体-绑定
int socket_bind(const char *argv[])
{
    // 1.创建套接字     /本地通信  /UDP
    int sockfd = socket(AF_UNIX, SOCK_DGRAM, 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");
    
    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);

    //通信
    char buff[128] = {0};
    while (1)
    {
        printf("请输入 : ");
        fgets(buff,sizeof(buff), stdin);
        buff[strlen(buff) - 1] = '\0'; //清除 \n
        
        //发送数据
        if (-1 == sendto(sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&server_addr, server_addr_len))
            ERRLOG("send error");
        
        //接收应答
        if (-1 == recvfrom(sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&server_addr, &server_addr_len))
            ERRLOG("recv error");
        
        printf("服务器应答[%s]\n", buff);
    }
    //关闭监听套接字  一般不关闭
    close(sockfd);

    return 0;
}

//创建套接字-填充服务器网络信息结构体-绑定
int socket_bind(const char *argv[])
{
    // 1.创建套接字     /本地通信  /UDP
    int sockfd = socket(AF_UNIX, SOCK_DGRAM, 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套接字

绑定 ;还得 填充

服务器信息

信息结构体


填充

服务器信息

信息结构体

:以便于发送数据


sendto (sockfd, buff,sizeof(buff), 0, (struct sockaddr *)&server_addr, server_addr_len))


2. 报错 :


bind error: Address already in use


因为已经执行一次 套节字文件 已经存在

所以 只需要

删除

套节字文件 即可



版权声明:本文为qq_47355554原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。