로컬 소켓(도메인)

        로컬 소켓은 TCP/UDP 소켓과 다른 특별한 유형의 소켓입니다. TCP/UDP가 로컬 주소에서 통신하더라도 여전히 시스템 네트워크 프로토콜 스택을 통과해야 합니다. 엄밀히 말하면 로컬 소켓은 단일 호스트의 크로스 프로세스 호출 수단을 제공하므로 프로토콜 스택의 복잡성과 효율성이 줄어듭니다. 구현 TCP/UDP 소켓보다 훨씬 높습니다. 로컬 소켓은 로컬 프로세스 간 통신을 구현한 IPC입니다.

로컬 소켓의 역할: 관련 프로세스 간  통신  과  관련되지 않은 프로세스 간 통신을
실현할 수 있는  로컬 프로세스 간 통신 로컬 소켓 구현 프로세스는 네트워크 소켓 구현 프로세스와 유사하며 일반적으로 TCP 통신 프로세스를 사용합니다. 

주소 구조 비교(로컬 대 네트워크)

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文件名(含路径)
};

프로그래밍 아이디어 비교(로컬 대 네트워크)

로컬 소켓 - 프로세스 간 통신 프로세스 

서비스 터미널

1. 청취 소켓 생성
      int lfd = 소켓(af_local, sock_stream, 0),
          첫 번째 매개변수: AF_UNIX, AF_LOCAL

2. 청취 소켓은 로컬 소켓 파일에 바인딩됩니다 -> 서버 측
      struct sockaddr_un addr;
      // 바인딩이 성공한 후 지정된 sun_path의 소켓 파일은 자동으로
      바인딩(lfd, addr, len)을 생성합니다.

3.
      듣기(lfd, 100);

4. 연결 요청을 기다렸다가 수락합니다
      struct sockaddr_un cliaddr;
      int connfd = accept(lfd, cliaddr, len);

5. 데이터 수신을 위한 통신 :       데이터 전송을 위한
      읽기/수신 : 쓰기/전송

6. 연결을 닫습니다.
      close();

고객

1. 통신 소켓을 생성합니다.
      int fd = 소켓(af_local, sock_stream, 0);

2. 청취 소켓은 로컬 IP 포트
      struct sockaddr_un addr에 바인딩됩니다.
      // 바인딩이 성공한 후 지정된 sun_path의 소켓 파일은 자동으로
      바인딩(fd, addr, len)을 생성합니다.

3. 서버에 연결
      struct sockaddr_un serveraddr;
      connect(fd, serveraddr, sizeof(serveraddr));

4. 데이터 수신을 위한 통신
      : 읽기/수신
      및 데이터 전송: 쓰기/전송

5. 연결을 닫습니다

암호

/* 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;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_43200943/article/details/130261444
Recomendado
Clasificación