13장 고급 입출력 함수 박사 4학기 최 성자
13-1. Recv & send 함수
recv & send read & write 함수와 달리 데이터 입 출력 방법에 있어서 옵션 부여. 옵션의 종류와 의미. #include <sys/types.h> #include <sys/socket.h> int recv(int sock, void * buf, int len, unsigned int flags); int send(int sock, const void * buf, int len, unsigned int flags); [ 표 13-1 ] flags Description recv send MSG_DONTROUTE 데이터 전송 시 라우팅 테이블 참조 하지 않음. MSG_DONTWAIT 넌-블록킹(non-blocking) I/O MSG_OOB 데이터 전송 시, 긴급 데이터(Out-of-band data) 전송 MSG_PEEK 버퍼에 데이터 유 무 확인
긴급 데이터 전송 시 생성되는 패킷 긴급 데이터 전송을 위한 패킷의 형성 긴급 데이터 전송의 특징. - 버퍼 상황에 관계 없이 데이터 전송 - Nagle 알고리즘 무시 [ 그림 13-4 : 출력 버퍼 ] [ 그림 13-4 : TCP 패킷]
긴급 데이터 전송 예제[MSG_OOB] [oob_send.c] write(sock, "123", 3); send(sock, "4", 1, MSG_OOB); //긴급 메시지 송신 write(sock, "567", 3); send(sock, "890", 3, MSG_OOB); //긴급메시지 송신, urgent point –offset:3, “0”송신 [oob.recv.c] 29: struct sigaction act; // 긴급 메시지 처리위해 구조체 선언 37: act.sa_handler=urg_handler; //긴급메시지 수신 핸들 대입 sigemptyset(&act.sa_mask); act.sa_flags=0; 57: fcntl(send_sock, F_SETOWN, getpid()); //소켓의 핸들 소유를 현재 프로세스 대입 state=sigaction(SIGURG, &act, 0); if(state != 0) error_handling("sigaction() error "); 62: while( (str_len=recv(send_sock, buf, sizeof(buf), 0)) != 0) { // 일반 메시지 72: void urg_handler(int signo) //긴급 메시지 루틴선언 //urgent point는 긴급 수신 메시지 마지막 바이트 다음 위치 설정됨 76: str_len=recv(send_sock, buf, sizeof(buf)-1, MSG_OOB); // 긴급 메시지 처리
긴급 데이터 전송 예제[MSG_OOB] [ 그림 13-2 ] [ 그림 13-3 ]
입력 버퍼 검사 예제[MSG_PEEK] [peek_send.c] write(sock, "123", 3); [peek_recv.c] sleep(1); str_len=recv(send_sock, buf, sizeof(buf)-1, MSG_PEEK|MSG_DONTWAIT); buf[str_len]=0; printf("총 %d 바이트 존재합니다 : %s\n", str_len, buf); str_len=recv(send_sock, buf, sizeof(buf)-1, 0); printf("읽어 온 결과 입니다. : %s\n", buf);
입력 버퍼 검사 예제[MSG_PEEK] [ 그림 13-7 ] [ 그림 13-8 ]
13-2. readv & writev 함수 저자 윤 성 우 ripeness21@empal.com
readv & writev 함수의 데이터 입 출력 방식 Array 1 Array 1 Array 2 출력 버퍼 Array 2 출력 버퍼 Array 3 Array 3 [write 3번 호출 ] [writev 1번 호출 ] 2. 데이터를 분산 수신(readv) Array 1 Array 1 입력 버퍼 Array 2 입력 버퍼 Array 2 Array 3 Array 3 [read 3번 호출 ] [readv 1번 호출 ]
readv & writev 함수의 사용 배열을 정의하기 위한 구조체의 선언. struct iovec { ptr_t iov_base; size_t iov_len; } [그림 13-9 ]
readv & writev 함수 호출 예제 [writev.c] struct iovec vec[2]; // 2개의 버퍼 연결 구조체 선언 char MSG1[]="Computer "; //버퍼1 char MSG2[]="Communications"; //버퍼2 int str_len; vec[0].iov_base=MSG1; 구조체와 버퍼 연결 vec[0].iov_len=strlen(MSG1); vec[1].iov_base=MSG2; 구조체와 버퍼 연결 vec[1].iov_len=strlen(MSG2); str_len=writev(1, vec, 2); //콘솔 통해서 2개의 버퍼의 데이타를 한번에 송신 [readv.c] struct iovec vec[2]; char MSG1[10]={0,}; char MSG2[10]={0,}; int str_len; vec[0].iov_base=MSG1; //구조체와 실제 버퍼 연결1 vec[0].iov_len=9; vec[1].iov_base=MSG2; //구조체와 실제 버퍼 연결1 vec[1].iov_len=9; str_len=readv(0, vec, 2); //두개의 버퍼로 나누어 수신 printf("\n총 %d 바이트 입력\n", str_len); printf("첫 번째 메시지 : %s \n", MSG1); printf("두 번째 메시지 : %s \n", MSG2);
readv & writev 함수 호출 예제 [ 그림 13-10 ] [ 그림 13-11 ]
13-3. 윈도우즈 기반의 이해
윈도우즈 기반 OOB 데이터 송 수신 윈도우즈 기반에서는 signal 핸들링 이라는 개념이 존재하지 않는다. select 함수는 소켓을 통해서 예외 상황(OOB 데이터 수신)이 발생 하였는지 확인하는 것이 가능하다. [oob_recv_win.c] result = select(fd_max+1, &readCopy, 0, &exceptCopy, &timeout); if(result>0) { if(FD_ISSET(hSendSock, &exceptCopy)){ strLen=recv(hSendSock, buf, BUFSIZE-1, MSG_OOB); buf[strLen]=0; printf("긴급 메시지 전송 : %s \n", buf); } if(FD_ISSET(hSendSock, &readCopy)){ strLen = recv(hSendSock, buf, BUFSIZE-1, 0); if(strLen ==0) break; else { puts(buf); [oob_send_win.c] send(hSocket, "123", 3, 0); send(hSocket, "4", 1, MSG_OOB); send(hSocket, "567", 3, 0); send(hSocket, "890", 3, MSG_OOB);
프로젝트생성 Setting -> *WS2_32.lib 추가 컴파일해야함