실습3: 앞서 실습한 file_server.c, file_client.c 는 server에서 client 접속시 파일을 전송한다. 이번에는 반대로 서버는 select를 이용해 구현하고, client에서 파일을 전송하도록 해보자, //echo_selectserv.c 사용해도댐

( 어제한건 서버->클라로 파일 전송 )

file_client.c

 
file
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
 
// client.c
 
#define BUF_SIZE 30
void error_handling(char *message);
 
int main(int argc, char *argv[])
{
    int sd;
    FILE *fp;
 
    char buf[BUF_SIZE];
    int read_cnt;
    int clnt_sd;
    
    struct sockaddr_in serv_adr;
    if(argc!=3) {
        printf("Usage: %s <IP> <port>\n", argv[0]);
        exit(1);
    }
 
    fp=fopen("6_all_makefile.zip","rb");
    sd=socket(PF_INET, SOCK_STREAM, 0);
 
    memset(&serv_adr, 0sizeof(serv_adr));
    serv_adr.sin_family=AF_INET;
    serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
    serv_adr.sin_port=htons(atoi(argv[2]));
 
    clnt_sd=connect(sd, (struct sockaddr*)&serv_adr, sizeof(serv_adr));
 
     while(1)
    {
        read_cnt=fread((void*)buf,1,BUF_SIZE,fp);
        if(read_cnt<BUF_SIZE)
        {
            write(sd, buf, read_cnt);
            break;
        }
        write(sd, buf, BUF_SIZE);
    }
 
 
    fclose(fp);
    close(sd);
    
    return 0;
}
 
void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n',stderr);
    exit(1);
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

 

 

 

표준 입출력 함수의 장점

 

표준 입출력 함수의 두 가지 장점

  • 표준 입출력 함수는 이식성(Protability)이 좋다.
  • 표준 입출력 함수는 버퍼링을 통한 성능의 향상에 도움이 된다.

ANSI C 기반의 표준 입출력 함수는 모든 컴파일러에서 지원을 하기 때문에 이식성이 좋아진다.

표준 입출력 함수를 이용해 데이터를 전송할 경우 소켓의 입출력 버퍼 이외의 버퍼를 통해서 버퍼링이 된다.

 

 

 

표준 입출력 함수와 시스템 함수의 성능비교

dd if=/dev/zero of=test100M count=1 bs=100M

 

syscpy.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <fcntl.h>
#define BUF_SIZE 3
 
int main(int argc, char *argv[])
{
    int fd1, fd2, len;
    char buf[BUF_SIZE];
 
    fd1=open("news.txt", O_RDONLY);
    fd2=open("cpy.txt", O_WRONLY|O_CREAT|O_TRUNC);
 
    while((len=read(fd1, buf, sizeof(buf)))>0)
        write(fd2, buf, len);
 
    close(fd1);
    close(fd2);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

시스템 함수를 이용해서 버퍼링 없는 파일 복사를 진행

 

stdcpy.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#define BUF_SIZE 3
 
int main(int argc, char *argv[])
{
    FILE * fp1;
    FILE * fp2;
    char buf[BUF_SIZE];
    
    fp1=fopen("news.txt""r");
    fp2=fopen("cpy.txt""w");
 
    while(fgets(buf, BUF_SIZE, fp1)!=NULL)
        fputs(buf, fp2); 
 
    fclose(fp1);
    fclose(fp2);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

표준 입출력 함수를 이용해서 버퍼링 기반의 파일 복사를 진행

 

표준 입출력 함수의 사용에 있어서 불편사항

 

리눅스에서의 send & recv

#include <sys/socket.h>

ssize_t send(int sockfd, const void * buf, size_t nbytes, int flags);

  • sockfd 데이터 전송 대상과의 연결을 의미하는 소켓의 파일 디스크립터 전달.
  • buf 전송할 데이터를 저장하고 있는 버퍼의 주소 값 전달.
  • nbytes 전송할 바이트 수 전달
  • flags 데이터 전송 시 적용할 다양한 옵션 정보 전달.

ssize_t recv(int sockfd, void * buf, sizt_t nbytes, int flags);

  • sockfd 데이터 수신 대상과의 연결을 의미하는 소켓의 파일 디스크립터 전달
  • buf 수신된 데이터를 저장할 버퍼의 주소 값 전달.
  • nbytes 수신할 수 있는 최대 바이트 수 전달
  • flags 데이터 수신 시 적용할 다양한 옵션 정보 전달

 

옵션(Option) 의미 send recv
MSG_OOB 긴급 데이터(Out-of-band data)의 전송을 위한 옵션

MSG_PEEK 입력버퍼에 수신된 데이터의 존재유무 확인을 위한 옵션  

MSG_DONTROUTE 데이터 전송과정에서 라우팅(Routing) 테이블을 참조하지 않을 것을 요구하는 옵션, 따라서 로컬(Local) 네트워크 상에서 목적지를 찾을 때 사용되는 옵션

 
MSG_DONTWAIT 입출력 함수 호출과정에서 블로킹 되지 않을 것을 요구하기 위한 옵션, 즉, 넌-블로킹(Non-blocking) IO의 요구에 사용되는 옵션

MSG_WAITALL 요청한 바이트 수에 해당하는 데이터가 전부 수신될 때까지, 호출된 함수가 반환되는 것을 막기 위한 옵션  

데이터의 전송에 사용되는 옵션정보이다. 옵션정보는 | 연산자를 이용해서 둘 이상을 동시에 지정 가능하다. 그러나 옵션의 종류와 지원여부는 운영체제에 따라서 차이가 있다.

 

MSG_OOB : 긴급 메시지의 전송

oob_send.c

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
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define BUF_SIZE 30
void error_handling(char *message);
 
int main(int argc, char *argv[])
{
    int sock;
    struct sockaddr_in recv_adr;
 
    if(argc!=3) {
        printf("Usage : %s <IP> <port>\n", argv[0]);
        exit(1);
     }
 
    sock=socket(PF_INET, SOCK_STREAM, 0);
     memset(&recv_adr, 0sizeof(recv_adr));
    recv_adr.sin_family=AF_INET;
    recv_adr.sin_addr.s_addr=inet_addr(argv[1]);
    recv_adr.sin_port=htons(atoi(argv[2]));
  
    if(connect(sock, (struct sockaddr*)&recv_adr, sizeof(recv_adr))==-1)
        error_handling("connect() error!");
    
    write(sock, "123", strlen("123"));
    send(sock, "4", strlen("4"), MSG_OOB);
    write(sock, "567", strlen("567"));
    send(sock, "890", strlen("890"), MSG_OOB);
    close(sock);
    return 0;
}
 
void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

MSB_OOB 메시지를 받으면 SIGURG 시그널이 발생한다. 따라서 이에 대한 처리를 위해서 시그널 핸들링이 필요하다. 단, fcntl 함수의 호출을 통해 해당 소켓의 소유자를 현재 실행중인 프로세스로 변경해야 한다.

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
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
 
#define BUF_SIZE 30
void error_handling(char *message);
void urg_handler(int signo);
 
int acpt_sock;
int recv_sock;
 
int main(int argc, char *argv[])
{
    struct sockaddr_in recv_adr, serv_adr;
    int str_len, state;
    socklen_t serv_adr_sz;
    struct sigaction act;
    char buf[BUF_SIZE];
 
    if(argc!=2) {
        printf("Usage : %s <port>\n", argv[0]); 
        exit(1);    
     }
    
    act.sa_handler=urg_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0
    
    acpt_sock=socket(PF_INET, SOCK_STREAM, 0);
    memset(&recv_adr, 0sizeof(recv_adr));
    recv_adr.sin_family=AF_INET;
    recv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    recv_adr.sin_port=htons(atoi(argv[1]));
 
    if(bind(acpt_sock, (struct sockaddr*)&recv_adr, sizeof(recv_adr))==-1)
        error_handling("bind() error");
    listen(acpt_sock, 5);
 
    serv_adr_sz=sizeof(serv_adr);
    recv_sock=accept(acpt_sock, (struct sockaddr*)&serv_adr, &serv_adr_sz);
    
    fcntl(recv_sock, F_SETOWN, getpid()); 
    state=sigaction(SIGURG, &act, 0);
    
    while((str_len=recv(recv_sock, buf, sizeof(buf), 0))!= 0
    {
        if(str_len==-1)
            continue;
        buf[str_len]=0;
        puts(buf);
    }
    close(recv_sock);
    close(acpt_sock);
    return 0
}
 
void urg_handler(int signo)
{
    int str_len;
    char buf[BUF_SIZE];
    str_len=recv(recv_sock, buf, sizeof(buf)-1, MSG_OOB);
    buf[str_len]=0;
    printf("Urgent message: %s \n", buf);
}
 
void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

실행 결과를 보면, 긴급으로 메시지가 전달 된 흔적이 보이지 않는다. 이렇듯 MSG_OOB는 우리가 생각하는 긴급의 형태와 다르다.

실행결과의 판단

MSG_OOB 메시지라고 해서 더 빨리 전송되지 않는다.

긴급으로 보낸 메시지의 양에 상관 없이 1바이트만 반환이 된다.

 

 

+ Recent posts