Linux网络编程----本地套接字

本地套接字与网络套接字的区别:

1.网络套接字是通过绑定ip和端口使网络中的进程之间进行通信,而本地套接字是绑定套接字文件的路径名来使单机中的进程间通信,是一种IPC机制,其存储地址结构的数据类型为struct sockaddr_un,该数据类型包含在#include头文件中

  #define UNIX_PATH_MAX 108
  struct sockaddr_un {
  		sa_family_t sun_family; /*PF_UNIX或AF_UNIX */
  		char sun_path[UNIX_PATH_MAX]; /* 路径名 */
  };

2.网络套接字客户端可以隐式绑定ip和端口,但是本地套接字客户端必须绑定套接字文件的路径名,否则无法通信(因为本地套接字通信模式中bind函数会创建套接字文件,两个进程之间的通信是通过各自的套接字文件来进行的)

除了以上两点外,本地套接字通信模式与网络套接字基本相同,我们可以直接看代码:

TCP(字节流套接字)

server.c

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
int main(void)
{
    int lfd,len,cfd,ret;
    char buf[BUFSIZ];
    struct sockaddr_un serv_addr,clie_addr;
    socklen_t clie_addr_len = sizeof(clie_addr);

    //绑定地址结构
    serv_addr.sun_family = AF_UNIX;
    strcpy(serv_addr.sun_path,SERVER_PATH);

    lfd = socket(AF_UNIX,SOCK_STREAM,0);//建立本地套接字 AF_UNIX参数代表创建的是本地套接字
    if(lfd == -1)
    {
        perror("socket error");
        exit(1);
    }

    len = offsetof(struct sockaddr_un,sun_path) + strlen(serv_addr.sun_path);//获取serv_addr实际存储数据的长度
    unlink(SERVER_PATH);//若文件存在则删除文件,防止bind创建文件失败
    ret = bind(lfd,(struct sockaddr*)&serv_addr,len);//绑定地址结构并创建套接字文件
    if(ret == -1) 
    {   
        perror("bind error");
        exit(1);
    }   

    listen(lfd,128);
    while(1)
    {
        cfd = accept(lfd,(struct sockaddr*)&clie_addr,&clie_addr_len);
        if(cfd == -1)
        {
            perror("accept error");
            exit(1);
        }
        while(1)
        {
            int n = read(cfd,buf,sizeof(buf));
            if(n == -1)
            {
                perror("read error");
                exit(1);
            }
            else if(n == 0)
            {
                close(cfd);
                break;
            }
            for(int i = 0;i < n;i++)
                buf[i] = toupper(buf[i]);
            write(cfd,buf,n);
        }
    }
    close(lfd);
    return 0;
}

client.c

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
#define CLIENT_PATH "clie_sock_file"
int main(void)
{
    int cfd,len,ret;
    char buf[BUFSIZ];
    struct sockaddr_un ser_addr,cli_addr;

    cli_addr.sun_family = AF_UNIX;
    strcpy(cli_addr.sun_path,CLIENT_PATH);

    cfd = socket(AF_UNIX,SOCK_STREAM,0);
    
    len = offsetof(struct sockaddr_un,sun_path) + strlen(cli_addr.sun_path);
    unlink(CLIENT_PATH);
    bind(cfd,(struct sockaddr*)&cli_addr,(socklen_t)len);

    ser_addr.sun_family = AF_UNIX;
    strcpy(ser_addr.sun_path,SERVER_PATH);
    
    len = offsetof(struct sockaddr_un,sun_path) + strlen(ser_addr.sun_path);
    ret = connect(cfd,(struct sockaddr*)&ser_addr,len);
    if(ret == -1) 
    {   
        perror("connect error");
        exit(1);
    }   
    while(fgets(buf,sizeof(buf),stdin) != NULL)
    {
        write(cfd,buf,strlen(buf));
        int n = read(cfd, buf,sizeof(buf));
        if(n == -1)
        {
            perror("read error");
            exit(1);
        }
        else if(n == 0)
            break;
        write(STDOUT_FILENO,buf,n);
    }
    close(cfd);
    return 0;
}

UDP(数据报套接字)

server.c

#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
int main(void)
{
    int sockfd,len;
    char buf[BUFSIZ];
    struct sockaddr_un ser_addr,cli_addr;
    socklen_t cli_addr_len = sizeof(cli_addr);

    sockfd = socket(AF_UNIX,SOCK_DGRAM,0);

    ser_addr.sun_family = AF_UNIX;
    strcpy(ser_addr.sun_path,SERVER_PATH);

    unlink(SERVER_PATH);
    len = offsetof(struct sockaddr_un,sun_path) + strlen(ser_addr.sun_path);
    bind(sockfd,(struct sockaddr*)&ser_addr,len);

    while(1)
    {   
        int n = recvfrom(sockfd,buf,sizeof(buf),0,(struct
                    sockaddr*)&cli_addr,&cli_addr_len);
        if(n == -1) 
        {   
            perror("recvfrom error");
            exit(1);
        }   
        for(int i = 0; i < n ;i++)
            buf[i] = toupper(buf[i]);
        sendto(sockfd,buf,n,0,(struct sockaddr*)&cli_addr,sizeof(cli_addr));
    }
    close(sockfd);
    return 0;
}

client.c

#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PATH "serv_sock_file"
#define CLIENT_PATH "clie_sock_file"
int main(void)
{
    int sockfd,len;
    char buf[BUFSIZ];
    struct sockaddr_un ser_addr,cli_addr;
    
    sockfd = socket(AF_UNIX,SOCK_DGRAM,0);

    cli_addr.sun_family = AF_UNIX;
    strcpy(cli_addr.sun_path,CLIENT_PATH);

    unlink(CLIENT_PATH);
    len = offsetof(struct sockaddr_un,sun_path) + strlen(cli_addr.sun_path);
    bind(sockfd,(struct sockaddr*)&cli_addr,len);

    ser_addr.sun_family = AF_UNIX;
    strcpy(ser_addr.sun_path,SERVER_PATH);
    len = offsetof(struct sockaddr_un,sun_path) + strlen(ser_addr.sun_path);

    while(fgets(buf,sizeof(buf),stdin) != NULL)
    {   
        sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&ser_addr,len);

        recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
        write(STDOUT_FILENO,buf,strlen(buf));
    }   
    close(sockfd);
    return 0;
}

你可能感兴趣的:(linux网络编程)