리눅스

Unix Domain Socket

개발새발 2020. 4. 12. 15:18
반응형

IPC를 위한 방법으로 파이프,메세지큐,세마포어,소켓등이 있다. 개발하려는 프로그램의 방향에따라 적적한 방식을 택하면 된다.

 

그 중 소켓을 이용한 IPC는 기존의 네트워크 통신 방식과 동일하다.(어짜피 네트워크 소켓도 프로세스간의 통신을 위한 것이기 때문에) 그래서 API사용에 있어서 좀더 익숙하고 기존의 네트워크 방식을 로컬방식으로 옮길때 코드상의 큰 수정없이 바로 적용가능하다. 그리고 양방향 통신을 위해 파이프방식 처럼 길을 두개 열어줄 필요가 없이 양방향 통신이 가능하다. 어느정도 규모가 있는 프로그램은 소켓을 이용하기를 추천하고 있다.(아마도 대부분 서버-클라이언트 구조라서 그러는 것 같음.) 뿐만아니라 로컬에서의 통신이기 때문에 UDP방식을 사용하더라도 패킷 유실의 걱정도 없다.

기존의 네트워크 상에서 소켓 통신과 달라지는 점은 sock_addr_in 구조체를 sock_addr_un으로 변경해주고 속성을 AF_INET을 AF_UNIX로 변경해주면 된다. +소켓 통신을 하기 위한 파일 경로가 필요하다. (아래의 예제에서는 앱이 실행되는 현재 경로의 test_server라는 파일을 사용한다.)

 

예제 코드

 

[Sever]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/un.h>
 
#define BUF_SIZE 1024
#define FILE_SERVER "./test_server"//file path
 
int main(void){
 
    int server_socket;
 
    int client_socket;
 
    int client_addr_size;
 
    int option;
 
 
 
    struct sockaddr_un server_addr;
 
    struct sockaddr_un client_addr;
 
 
 
    char buff_rcv[BUF_SIZE];
 
    char buff_snd[BUF_SIZE];
 
 
 
    if(!access(FILE_SERVER, F_OK))//if file exist
 
        unlink(FILE_SERVER);
 
 
 
    server_socket = socket(AF_UNIX, SOCK_STREAM, 0);//create unix socket(TCP)
 
 
 
    if(server_socket == -1){
 
        printf("server socket error!\n");
 
        exit(1);
 
    }
 
 
 
    memset(&server_addr, 0sizeof(server_addr));
 
    server_addr.sun_family = AF_UNIX;
 
    strcpy(server_addr.sun_path, FILE_SERVER);
 
    
 
    if(bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) ==-1){
 
        printf("bind error!\n");
 
        exit(1);
 
    }
 
 
 
    while(1){
 
        if(listen(server_socket, 5== -1){
 
            printf("listen error! \n");
 
            exit(1);
 
        }
 
 
 
        client_addr_size = sizeof(client_addr);
 
        client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_size);
 
 
 
        if(client_socket == -1){
 
            printf("accept failed!\n");
 
            exit(1);
 
        }
 
 
 
        read(client_socket, buff_rcv, BUF_SIZE);
 
        printf("received msg : %s\n",buff_rcv);
 
        strcpy(buff_snd,"ACK");
 
 
 
        write(client_socket, buff_snd, strlen(buff_snd)+1);
 
        close(client_socket);
 
    }
 
    return 0;
 
}      
cs

[Client]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/un.h>
 
#define BUFF_SIZE 1024
#define FILE_SERVER "./test_server"//file path
 
 
int main(void){
 
    int client_socket;
 
    char * msg = "Hello World!";
 
    struct sockaddr_un server_addr;
 
    char buff[BUFF_SIZE];
 
 
 
    client_socket = socket(AF_UNIX, SOCK_STREAM, 0);
 
 
 
    if(client_socket == -1){
 
        printf("socket create fail!\n");
 
        exit(1);
 
    }
 
 
 
    memset(&server_addr, 0sizeof(server_addr));
 
    server_addr.sun_family = AF_UNIX;
 
    strcpy(server_addr.sun_path, FILE_SERVER);
 
 
 
    if(connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
 
        printf("connect fail!\n");
 
        exit(1);
 
    }
 
    
 
    write(client_socket, msg, strlen(msg)+1);
 
    read(client_socket, buff, BUFF_SIZE);
 
    printf("recv msg from server : %s\n",buff);
 
    close(client_socket);
 
 
 
    return 0;
 
}
cs
반응형