Half_close_File_Transmission.zip
- closesocket() : 일방적인 완전 종료, 데이터 전송과 수신이 더이상 불가능.
=> 수신 도중 연결이 종료 되면 수신 데이터가 날아감
- 스트림 : 서로 송수신이 가능한 상태
각 Host 간에 소켓이 연결되면, 각 Host에 입력 스트림과 출력 스트림이 생성
closesocket()은 둘 다 끊어버림
- Half-close
#include <winsock2.h>
int shutdown(
SOCKET sock, // 종료할 소켓의 핸들
int howto // 종료 방법
); // 성공 : 0, 실패 : SOCKET_ERROR
> howto 인자
SD_RECEIVE : 입력 스트림 종료 (데이터 수신 불가)
SD_SEND : 출력 스트림 종료 (데이터 송신 불가)
SD_BOTH : 입출력 스트림 종료
- 출력 스트림을 Half-close할 경우 EOF를 전송함 -> 입력 스트림으로 상대에 대한 답변을 받을 수 있음.
- DNS(Domain Name System)
> DNS(기억하고 표현하기 좋은 형태) <-> IP
> LAN [ PC -> Default DNS Server ] -> DNS Server -> Root DNS Server(최상위)
-> DNS Server -> LAN [Default DNS Server, Destination Server](IP 얻음)
> IP 얻은 다음 역순으로 결과를 전달하여 질의 를 시작한 host에 IP주소 전달
> 계층적으로 관리되는 일종의 분산 데이터베이스 시스템
- ping & nslookup
ping : 도메인 이름으로 IP 주소 확인
nslookup : 사용하는 컴퓨터에 등록되어 있는 Default DNS 서버의 주소 확인
- 도메인 이름으로 IP주소 얻기
#include <winsock2.h>
struct hostent* gethostbyname(const char* name);
// 성공 : hostent 구조체 변수의 주소 값, 실패 : NULL
- IP주소로 도메인 정보 얻기
#include <winsock2.h>
struct hostent* gethostbyaddr(const char* addr, int len, int type);
// 성공 : hostent 구조체 변수의 주소 값, 실패 : NULL
struct hostent
{
char* h_name; // 공식 도메인 이름
char** h_aliases; // 공식 도메인 외에 해당 메인 페이지 접속 할 수 있는 도메인
int h_addrtype; // IP 주소 체계
int h_length; // IP 주소 크기 정보, IPv4 : 4, IPv6 : 16
char** h_addr_list; // 정수 형태의 IP주소 (void* 형태가 어울리지만 이미 오래전에 정해졌으므로)
};
- 소켓 옵션 변경
int getsockopt(
int sock, // 옵션 확인할 소켓
int level, // 확인할 옵션의 프로토콜 레벨
int optname, // 확인할 옵션의 이름
char* optal, // 확인 결과를 저장할 버퍼
socklen_t* optlen // 버퍼크기, 함수가 끝나면 네 번째 인자로 옵션 정보 크기가 바이트 단위로 저장
);
int setsockopt(
int sock, // 옵션 변경할 소켓
int level, // 변경할 옵션의 프로토콜 레벨
int optname, // 변경할 옵션의 이름
const char* optal, // 변경 옵션 정보 버퍼
socklen_t* optlen // 버퍼크기
);
* SO_TYPE(소켓 타입) (확인만 가능 변경 불가)
-> 소켓 타입은 소켓 생성시 한번 결정되면 변경이 불가능 하다.
- SO_SNDBUF(출력 버퍼 크기), SO_RCVBUF(입력 버퍼 크기)
-> 버퍼의 크기는 요구사항 대로 정확히 설정돼지 않는다.
- SO_REUSEADDR
> 주소할당 에러 발생
-> 서버와 클라가 연결된 상태에서 서버를 강제 종료
=> 서버가 클라 쪽에 먼저 FIN 메시지 전달
=> 서버가 바로 재실행 되지 않고 bind()에서 에러 (Time-wait 상태)
> Time-wait 상태
-> Four-way handshaking 이후 소켓이 바로 소멸 되지 않고 Time-wait 상태라는 일정 시간 거침
-> Time-wait 상태에 있는 동안 해당소켓의 PORT번호는 사용중인 상태 => bind()에서 오류남
-> 클라나 서버 상관없이 먼저 연결 종료하는 소켓에 일어남
-> 하지만 클라 소켓의 PORT 번호는 임의로(유동적으로) 할당 되므로 신경 쓰지 않아도 됨
-> 상대 호스트로 보내는 마지막 ACK가 전송 실패를 대비해서 기다려 주는 것이 Time-wait 상태
> 주소의 재할당
-> Time-wait 상태는 마지막 ACK가 전송 실패 할경우 더 길어 질 수 있음
(Time-wait 상태에서 다시 상대 host에서 FIN 받고 Time-wait가 재가동)
-> 해결책 : SO_REUSEADDR 상태를 변경
Time-wait 상태에 있는 소켓에 할당된 PORT 번호를 새로 시작하는 소켓에 할당 할 수 있음
SO_REUESEADDR의 default 값은 0(FALSE) <- 이것을 1(TRUE) 바꿈
ex)
int option = TRUE;
int optlen = sizeof(option);
setsockopt(hServsock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, optlen);
> TCP_NODELAY
-> Nagle 알고리즘 : 앞서 전송한 데이터에 대한 ACK 메시지를 받아야만 다음 데이터 전송
(ACK 메시지 받기 전까지 출력버퍼에 데이터 쌓아놓고 있음)
알고리즘을 사용안하면 ACK 메시지 기다리지 않고
바로바로 데이터 전송하고 그때 그때 ACK 메시지 받음
-> 용량이 큰 파일 데이터의 전송 : 데이터를 출력버퍼로 밀어 넣는 작업은 시간이 걸리지 않음
=> Nagle 알고리즘을 사용하지 않아도 출력버퍼를 거의 가득 채운 상태로 패킷 전송
패킷 수가 크게 증가 하지 않고 ACK를 기다리지 않고 연속해서 데이터를 보내 속도가 빠름
-> 일반적으로는 Nagle을 적용 하지 않으면 속도가 향상 되지만 트래픽에 부담을 줌
=> 데이터 특성을 정확히 판단하여 Nagle 알고리즘 중지
ex)
[알고리즘 중단 적용]
int opt_val = 1;
setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&opt_val, sizeof(opt_val);
[확인]
int opt_val;
socklen_t opt_len;
opt_len = sizeof(opt_val);
getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&opt_val, &opt_len);
// opt_val이 0이면 Nagle알고리즘 설정, 1이면 Nagle알고리즘 설정 안됨
'programing > Networks' 카테고리의 다른 글
입출력 함수 (0) | 2015.05.18 |
---|---|
IO 멀티플렉싱 기반 서버 (0) | 2015.05.15 |
UDP 기반 서버 / 클라 (0) | 2015.05.14 |
TCP 기반 서버 / 클라 (0) | 2015.05.13 |
주소 체계와 데이터 정렬 (0) | 2015.05.12 |