local socket(domain)

        Local sockets are a special type of socket, different from TCP/UDP sockets. Even if TCP/UDP communicates at a local address, it still needs to go through the system network protocol stack. Strictly speaking, local sockets provide a means of cross-process calls from a single host, which reduces the complexity and efficiency of protocol stack implementation. Much higher than TCP/UDP sockets. Local sockets are IPC, which is an implementation of local inter-process communication.

The role of local sockets:  local inter-process communication,
which can realize  communication between related processes  and  communication between processes that are not related.
The local socket implementation process is similar to that of network sockets, and generally uses the TCP communication process. 

Address structure comparison (local vs. network)

struct sockaddr_in {
__kernel_sa_family_t sin_family; 			/* Address family */  	地址结构类型
__be16 sin_port;					 	    /* Port number */		端口号
struct in_addr sin_addr;					/* Internet address */	IP地址
};

struct sockaddr_un {
__kernel_sa_family_t sun_family; 		/* AF_UNIX */			地址结构类型
char sun_path[UNIX_PATH_MAX]; 		    /* pathname */		socket文件名(含路径)
};

Comparison of programming ideas (local vs. network)

Local socket—inter-process communication process 

Service-Terminal

1. Create a listening socket
      int lfd = socket(af_local, sock_stream, 0);
          first parameter: AF_UNIX, AF_LOCAL

2. The listening socket is bound to the local socket file -> server side
      struct sockaddr_un addr;
      // After the binding is successful, the socket file in the specified sun_path will automatically generate
      bind(lfd, addr, len) ;

3.
      Listen(lfd, 100);

4. Wait for and accept the connection request
      struct sockaddr_un cliaddr;
      int connfd = accept(lfd, cliaddr, len);

5. Communication
      to receive data: read/recv
      to send data: write/send

6. Close the connection
      close();

client

1. Create a communication socket
      int fd = socket(af_local, sock_stream, 0);

2. The listening socket is bound to the local IP port
      struct sockaddr_un addr;
      // After the binding is successful, the socket file in the specified sun_path will automatically generate
      bind(fd, addr, len);

3. Connect to the server
      struct sockaddr_un serveraddr;
      connect(fd, serveraddr, sizeof(serveraddr));

4. Communication
      to receive data: read/recv
      and send data: write/send

5. Close the connection

Code

/* server.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stddef.h>

#include "wrap.h"

#define SERV_ADDR  "serv.socket"

int main(void)
{
    int lfd, cfd, len, size, i;
    struct sockaddr_un servaddr, cliaddr;
    char buf[4096];

    lfd = Socket(AF_UNIX, SOCK_STREAM, 0);

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

    len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);     /* servaddr total len */

    unlink(SERV_ADDR);                              /* 确保bind之前serv.sock文件不存在,bind会创建该文件 */
    Bind(lfd, (struct sockaddr *)&servaddr, len);           /* 参3不能是sizeof(servaddr) */

    Listen(lfd, 20);

    printf("Accept ...\n");
    while (1) {
        len = sizeof(cliaddr);  //AF_UNIX大小+108B

        cfd = Accept(lfd, (struct sockaddr *)&cliaddr, (socklen_t *)&len);

        len -= offsetof(struct sockaddr_un, sun_path);      /* 得到文件名的长度 */
        cliaddr.sun_path[len] = '\0';                       /* 确保打印时,没有乱码出现 */

        printf("client bind filename %s\n", cliaddr.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);
    }
    close(lfd);

    return 0;
}
/* client.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stddef.h>

#include "wrap.h"

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

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

    cfd = Socket(AF_UNIX, SOCK_STREAM, 0);

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

    len = offsetof(struct sockaddr_un, sun_path) + strlen(cliaddr.sun_path);     /* 计算客户端地址结构有效长度 */

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

    
    bzero(&servaddr, sizeof(servaddr));                                          /* 构造server 地址 */
    servaddr.sun_family = AF_UNIX;
    strcpy(servaddr.sun_path, SERV_ADDR);

    len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);   /* 计算服务器端地址结构有效长度 */

    Connect(cfd, (struct sockaddr *)&servaddr, len);

    while (fgets(buf, sizeof(buf), stdin) != NULL) {
        write(cfd, buf, strlen(buf));
        len = read(cfd, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, len);
    }

    close(cfd);

    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43200943/article/details/130261444
Recommended