■ 타임아웃
통신 제어 프로그램은 상대 장치의 상태에 따라 통신이 도중에 끊어질 수 있다.
만약 100바이트가 올것이 데이터 수신 중에 송신 쪽의 문제로 80바이트만 송신한 경우
수신을 도중에 멈추고 알람을 표시할 필요가 있다.
타이머는 이런 목적으로 사용한다.
타이머의 설정은 SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
를사용하고 설정된 데이터를 읽을 때는 GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)를 사용한다.
SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
인수
hFile :
CreateFile()이 반환한 핸들
lpCommTimeouts :
타이머의 값이 들어있는 COMMTIMEOUTS 구조체의 포인터
반환값
함수가 성공하면 0이 아니고 실패하면 0
typedef struct _COMMTIMEOUTS{
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
}COMMTIMEOUTS、*LPCOMMTIMEOUTS;
ReadIntervalTimeout
데이터를 수신할 때 한문자를 수신한 후 다음 문자를 수신할 때까지의 대기 시간으로
밀리초 단위로 설장한다. 이 대기 시간 만큼 기다린 후 입력이 없을 경우 수신한 데이터를
반환한다.
이 값이 0인 경우, 타이머는 사용하지 않는다.
이 값이 MAXDWORD로 ReadTotalTimeoutMultiplier와 ReadTotalTimeoutConstant가
0인 경우 지정한 수신 수를 수신 전이라도 읽기 작업에서 빠져서 수신 데이터를 반환한다.
ReadTotalTimeoutMultiplier
읽기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리초 단위의 곱하기 계수를 지정한다.
ReadTotalTimeoutConstant
읽기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리 초 단위로 지정하는 정수로
사용된다.
ReadTotalTimeoutMultiplier와 ReadTotalTimeoutConstant는 읽기 작업에 걸리는
총시간을 설정하는 변수들로 이 두변수가 0인 경우 읽기 작업에는
토탈 타임아웃 타이머가 사용하지 않는다.
WriteTotalTimeoutMultiplier
쓰기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리초 단위의 곱하기 계수를 지정한다.
WriteTotalTimeoutConstant
쓰기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리 초 단위로 지정하는 정수로
사용된다.
WriteTotalTimeoutMultiplier와 WriteTotalTimeoutConstant는 쓰기 작업에 걸리는
총시간을 설정하는 변수들로 이 두변수가 0인 경우 쓰기 작업에는
토탈 타임아웃 타이머가 사용하지 않는다.
어플리케이션이 ReadIntervalTimeout과 ReadTotalTimeoutMultilier를 MAXDWORD로 설정하고
MAXDWORD > ReadTotalTimeoutConstant > 0으로 설정하면
ReadFile함수가 사용될 때 아래와 같이 된다.
- 입력 버퍼에 수신 데이터가 있으면 ReadFile은 바로 버퍼의 문자를 반환한다.
- 입력 버퍼에 수신 데이터가 없으면 ReadFile은 수신할 때까지 기다렸다가 반환한다.
- ReadTotalTimeoutConstant에 의해 지정된 시간 이내에 1바이트라도 수신하지 않으면
ReadFile은 타임아웃이 된다.
■ 타이머의 시간 설정
구체적으로 어떻게 타이머의 시간을 설정하면 좋을까?
COMMTIMEOUTS 구조체의 변수를 보면 알 수 있는 것처럼 감시하는 대상은 2종류가 있다.
하나는 인터벌 시간이고 다른 하나는 토탈 시간이다.
인터벌 시간은 수신할 데이터 별로 타이머 감시를 하기 위한 것이기 때문에
예를들면 9600bps로 수신할 경우 1케릭터는 1ms정도이기 때문에 여유를 봐서
10ms이면 충분하다. (단 상대가 연속해서 데이터를 송신하는 경우이다.)
토털 시간은 이하의 계산식으로 계산된다. 이 두개의 감시시간을 넘으면 타임아웃이 발생한다.
타임아웃의 결과 수신 동작이나 송신 동자은 도중에 중단되고 수신일 때는
타임아웃이 발생한 시점까지의 데이터를 읽는다.
수신
ReadIntervalTimeout은 다음에 수신할 때 까지의 최대 대기 시간을 msec로 지정한다.
ReadTotalTimeoutMuliplier와 ReadTotalTimeoutConstant로 수신 토탈 시간을
이하의 식으로 계산한다.
수신 인터벌 시간 = ReadIntervalTimeout(msec)
수신 토탈 시간 =
(ReadTotalTimeoutMuliplier * 수신할 Byte수) + ReadTotalTimeoutConstant(msec)
송신
송신에는 데이터 간격 타이머는 없다.
WriteTotalTimeoutMuliplier와 WriteTotalTimeoutConstant로 송신 토탈 시간을
이하의 식으로 계산한다.
송신 토탈 시간 =
(WriteTotalTimeoutMuliplier * 송신할 Byte수) + WriteTotalTimeoutConstant(msec)
통신 제어 프로그램은 상대 장치의 상태에 따라 통신이 도중에 끊어질 수 있다.
만약 100바이트가 올것이 데이터 수신 중에 송신 쪽의 문제로 80바이트만 송신한 경우
수신을 도중에 멈추고 알람을 표시할 필요가 있다.
타이머는 이런 목적으로 사용한다.
타이머의 설정은 SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
를사용하고 설정된 데이터를 읽을 때는 GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)를 사용한다.
SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts)
인수
hFile :
CreateFile()이 반환한 핸들
lpCommTimeouts :
타이머의 값이 들어있는 COMMTIMEOUTS 구조체의 포인터
반환값
함수가 성공하면 0이 아니고 실패하면 0
typedef struct _COMMTIMEOUTS{
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
}COMMTIMEOUTS、*LPCOMMTIMEOUTS;
ReadIntervalTimeout
데이터를 수신할 때 한문자를 수신한 후 다음 문자를 수신할 때까지의 대기 시간으로
밀리초 단위로 설장한다. 이 대기 시간 만큼 기다린 후 입력이 없을 경우 수신한 데이터를
반환한다.
이 값이 0인 경우, 타이머는 사용하지 않는다.
이 값이 MAXDWORD로 ReadTotalTimeoutMultiplier와 ReadTotalTimeoutConstant가
0인 경우 지정한 수신 수를 수신 전이라도 읽기 작업에서 빠져서 수신 데이터를 반환한다.
ReadTotalTimeoutMultiplier
읽기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리초 단위의 곱하기 계수를 지정한다.
ReadTotalTimeoutConstant
읽기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리 초 단위로 지정하는 정수로
사용된다.
ReadTotalTimeoutMultiplier와 ReadTotalTimeoutConstant는 읽기 작업에 걸리는
총시간을 설정하는 변수들로 이 두변수가 0인 경우 읽기 작업에는
토탈 타임아웃 타이머가 사용하지 않는다.
WriteTotalTimeoutMultiplier
쓰기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리초 단위의 곱하기 계수를 지정한다.
WriteTotalTimeoutConstant
쓰기 작업을 위한 토탈 타임아웃 시간을 계산하기 위한 밀리 초 단위로 지정하는 정수로
사용된다.
WriteTotalTimeoutMultiplier와 WriteTotalTimeoutConstant는 쓰기 작업에 걸리는
총시간을 설정하는 변수들로 이 두변수가 0인 경우 쓰기 작업에는
토탈 타임아웃 타이머가 사용하지 않는다.
어플리케이션이 ReadIntervalTimeout과 ReadTotalTimeoutMultilier를 MAXDWORD로 설정하고
MAXDWORD > ReadTotalTimeoutConstant > 0으로 설정하면
ReadFile함수가 사용될 때 아래와 같이 된다.
- 입력 버퍼에 수신 데이터가 있으면 ReadFile은 바로 버퍼의 문자를 반환한다.
- 입력 버퍼에 수신 데이터가 없으면 ReadFile은 수신할 때까지 기다렸다가 반환한다.
- ReadTotalTimeoutConstant에 의해 지정된 시간 이내에 1바이트라도 수신하지 않으면
ReadFile은 타임아웃이 된다.
■ 타이머의 시간 설정
구체적으로 어떻게 타이머의 시간을 설정하면 좋을까?
COMMTIMEOUTS 구조체의 변수를 보면 알 수 있는 것처럼 감시하는 대상은 2종류가 있다.
하나는 인터벌 시간이고 다른 하나는 토탈 시간이다.
인터벌 시간은 수신할 데이터 별로 타이머 감시를 하기 위한 것이기 때문에
예를들면 9600bps로 수신할 경우 1케릭터는 1ms정도이기 때문에 여유를 봐서
10ms이면 충분하다. (단 상대가 연속해서 데이터를 송신하는 경우이다.)
토털 시간은 이하의 계산식으로 계산된다. 이 두개의 감시시간을 넘으면 타임아웃이 발생한다.
타임아웃의 결과 수신 동작이나 송신 동자은 도중에 중단되고 수신일 때는
타임아웃이 발생한 시점까지의 데이터를 읽는다.
수신
ReadIntervalTimeout은 다음에 수신할 때 까지의 최대 대기 시간을 msec로 지정한다.
ReadTotalTimeoutMuliplier와 ReadTotalTimeoutConstant로 수신 토탈 시간을
이하의 식으로 계산한다.
수신 인터벌 시간 = ReadIntervalTimeout(msec)
수신 토탈 시간 =
(ReadTotalTimeoutMuliplier * 수신할 Byte수) + ReadTotalTimeoutConstant(msec)
송신
송신에는 데이터 간격 타이머는 없다.
WriteTotalTimeoutMuliplier와 WriteTotalTimeoutConstant로 송신 토탈 시간을
이하의 식으로 계산한다.
송신 토탈 시간 =
(WriteTotalTimeoutMuliplier * 송신할 Byte수) + WriteTotalTimeoutConstant(msec)