Software Courses/Network

Application : Socket programming

김 정 환 2020. 12. 31. 15:28
반응형
본 내용은 한양대학교 이석복 교수님의 강의를 참고하여 정리하였습니다. 교재는 Pearson/Addison Wesley에서 출판한 Computer networking : a top-down approach입니다.

 

 

 

Socket 

    - 두 프로그램이 네트워크를 통해 서로 통신을 수행할 수 있도록 양쪽에 생성되는 인터페이스

    - 주로 TCP 기반 소켓과 UDP 기반 소켓을 사용

왼쪽: TCP 기반 소켓 , 오른쪽 : UDP 기반 소켓

 

 

 

동작

    - Server의 socket() : 소켓을 생성

    - Server의 bind() : 생성된 소켓에 IP address와 port 번호를 묶음

    - Server의 listen() : 서버는 클라이언트에서 연결 요청이 올 때까지 대기

    - Server의 accept() : 미결정 큐에 있던 연결 요청을 꺼내서 연결 생성

    - Server의 send()/recv() : 데이터 송수신

    - Server의 close() : 소켓 연결을 해제

 

    - Client의 socket() : 소켓을 생성

    - Client의 connect() : 서버와 연결하기 위해 요청

    - Client의 send()/recv() : 데이터 송수신

    - Client의 close() : 소켓 연결을 해제

    - Cline는 임의의 port 번호를 사용해도 되기 때문에 bind() 없어도 됨

 

 

 

구현 (C)

    - socket()

1
int socket(int domain, int type, int protocol)
cs

        * 소켓 생성

        * Return : file descriptor / -1

        * domain

            + PF_INET : IPv4 (일반적으로 사용)

            + AF_INET6 : IPv6

        * type

            + SOCK_STREAM : TCP 통신용

            + SOCK_DGRAM : UDP

        * protocol

            + IP 프로토콜 값으로 일반적으로 0으로 설정

 

 

    - bind()

1
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
cs

        * 생성된 소켓에 IP address와 port 번호를 묶음

        * Return : 0 / -1

        * sockfd : socket file descripter

        * addr : IP address와 port 번호를 포함하는 구조체

        * addrlen : 주소 구조체의 길이

 

 

    - listen()

1
int listen(int sockfd, int backlog)
cs

        * 서버는 클라이언트에서 연결 요청이 올 때까지 대기

        * Return : 0 / -1

        * sockfd : socket file descripter

        * backlog : 연결 요청들을 대기시키는 queue의 최대 길이. 만약에, queue가 모두 차있는 상태에서 연결 요청이 온다면, 클라이언트는 'ECONNREFUSED'라는 에러 메시지를 받음

 

 

    - accept()

1
int new_socket = accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
cs

        * 대기 큐에서 요청을 꺼내어 연결 생성

        * Return : 새로운 소켓 지정 번호 생성 / -1

        * addr : 클라이언트의 IP address와 port 번호

        * addrlen : 주소 구조체의 길이

 

 

    - connect()

1
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
cs

        * 서버와 연결하기 위해 요청

        * Return : 0 / -1

        * addr : 서버의 IP address와 port 번호를 포함하는 구조체

        * addrlen : 주소 구조체의 길이

 

 

    - 주소 구조체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct sockaddr {
    u_short sa_family;
    char    sa_data[14];
};
 
struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};
 
struct in_addr {
    __u32   s_addr;
};
 
cs

 

    - 서버 구현 전체 보기

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
#include <unistd.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#define PORT 8080
 
int main(int argc, char const *argv[]) 
    int server_fd, new_socket, valread; 
    struct sockaddr_in address; 
    int opt = 1
    int addrlen = sizeof(address); 
    char buffer[1024= {0}; 
    char *hello = "Hello from server";
 
       
    // socket file descriptor 생성
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0
    { 
        perror("socket failed"); 
        exit(EXIT_FAILURE); 
    } 
    
 
    // socket을 port 8080에 붙이기
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, 
                                                  &opt, sizeof(opt))) 
    { 
        perror("setsockopt"); 
        exit(EXIT_FAILURE); 
    } 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = INADDR_ANY; 
    address.sin_port = htons( PORT ); 
       
    // socket을 port 8080에 붙이기
    if (bind(server_fd, (struct sockaddr *)&address,  
                                 sizeof(address))<0
    { 
        perror("bind failed"); 
        exit(EXIT_FAILURE); 
    }
 
 
    // 요청 대기
    if (listen(server_fd, 3< 0
    { 
        perror("listen"); 
        exit(EXIT_FAILURE); 
    } 
 
    
    // 연결 승인
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address,  
                       (socklen_t*)&addrlen))<0
    { 
        perror("accept"); 
        exit(EXIT_FAILURE); 
    } 
 
    // 읽기
    valread = read( new_socket , buffer, 1024); 
    printf("%s\n",buffer );
 
    // 데이터 보내기
    send(new_socket , hello , strlen(hello) , 0 ); 
    printf("Hello message sent\n"); 
 
 
    return 0
cs

 

    - 클라이언트 구현 전체 보기

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
#include <stdio.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h> 
#define PORT 8080 
 
 
int main(int argc, char const *argv[]) 
    int sock = 0, valread; 
    struct sockaddr_in serv_addr; 
    char *hello = "Hello from client"
    char buffer[1024= {0};
 
    
    // socket file descriptor 생성
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0
    { 
        printf("\n Socket creation error \n"); 
        return -1
    } 
   
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(PORT); 
       
 
    // Convert IPv4 and IPv6 addresses from text to binary form 
    if(inet_pton(AF_INET, "127.0.0.1"&serv_addr.sin_addr)<=0)  
    { 
        printf("\nInvalid address/ Address not supported \n"); 
        return -1
    }
 
 
       // 연결 요청
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0
    { 
        printf("\nConnection Failed \n"); 
        return -1
    }
 
 
    send(sock , hello , strlen(hello) , 0 ); 
    printf("Hello message sent\n"); 
    valread = read( sock , buffer, 1024); 
    printf("%s\n",buffer ); 
 
    return 0
cs

 

 

 

 

참조

    - 블로그 1

    - 블로그 2    

    - 블로그 3

반응형

'Software Courses > Network' 카테고리의 다른 글

Transport : UDP  (0) 2020.12.31
Transport : Multiplexing, Demultiplexing  (0) 2020.12.31
Application : DNS  (0) 2020.12.30
Application : Proxy server  (0) 2020.12.30
Application : HTTP  (0) 2020.12.29