투케이2K
121. (java/자바) TCP/IP 소켓통신 및 시리얼(Serial)통신 시 사용되는 기본 데이터 수신(받은)로직 구현 본문
/* =========================== */
[ 개발 환경 설정 ]
개발 툴 : Eclipse
개발 언어 : Java
/* =========================== */
/* =========================== */
[전체 코드는 참고파일에서 다운받아주세요 - 코드 길이가 길어서 모두 올리지 못했습니다 ... ]
[부분 소스 코드]
// ==== [데이터 검증 및 버퍼 저장 메소드] ====
public static void getDataConfirm(byte[] data) {
System.out.println("[수신된 데이터 값] "+Arrays.toString(data));
if(dataBuffer.size() > 0) { //TODO 저장된 데이터가 있을 경우
if(data[0] == (byte)0x02 && data[data.length-1] == (byte)0x03) {
dataBuffer.clear(); //버퍼 초기화 실시
dataLen = data[2]&0xff; //헤더에서 데이터길이를 저장합니다
if(data.length >= (dataLen+3)){ //초기에 들어온 데이터가 (데이터길이+헤더길이)보다 크거나 같을 경우
for(int i=0; i<(dataLen+3); i++){ //(데이터길이+헤더길이) 만큼 받는다
dataBuffer.add(data[i]); //버퍼에 쌓는 부분
}
dataBuffer.add((byte)0x03); //버퍼에 쌓는 부분 (마지막 etx 저장)
System.out.println("[4단계 버퍼 저장] ["+String.valueOf(dataBuffer.size())+"]");
System.out.println("[저장된 데이터 값] "+dataBuffer.toString()+"");
System.out.println("");
getDataParsing(dataBuffer); //파싱하는 곳으로 보낸다
dataBuffer.clear(); //데이터 버퍼 공간을 초기화 시켜준다
dataLen = 0; //데이터길이 초기화
}
}
else if(data[0] == (byte)0x02 && data.length > 3) {
dataBuffer.clear(); //버퍼 초기화 실시
dataLen = data[2]&0xff; //헤더에서 데이터길이를 저장합니다
if(data.length >= (dataLen+3)){ //초기에 들어온 데이터가 (데이터길이+헤더길이)보다 크거나 같을 경우
for(int i=0; i<(dataLen+3); i++){ //(데이터길이+헤더길이) 만큼 받는다
dataBuffer.add(data[i]); //버퍼에 쌓는 부분
}
dataBuffer.add((byte)0x03); //버퍼에 쌓는 부분 (마지막 etx 저장)
System.out.println("[5단계 버퍼 저장] ["+String.valueOf(dataBuffer.size())+"]");
System.out.println("[저장된 데이터 값] "+dataBuffer.toString()+"");
System.out.println("");
getDataParsing(dataBuffer); //파싱하는 곳으로 보낸다
dataBuffer.clear(); //데이터 버퍼 공간을 초기화 시켜준다
dataLen = 0; //바디 길이 초기화
}
else{ //초기에 들어온 데이터가 데이터길이보다 작을 경우
for(int i=0; i<data.length; i++){ //전체 데이터를 다 받는다
dataBuffer.add(data[i]); //버퍼에 쌓는 부분
}
System.out.println("[6단계 버퍼 저장] ["+String.valueOf(dataBuffer.size())+"]");
System.out.println("[저장된 데이터 값] "+dataBuffer.toString()+"");
System.out.println("");
}
}
else {
for(int i=0; i<data.length; i++){
if(dataBuffer.size() == (dataLen+3)){ //(데이터길이+헤더길이)만큼 데이터를 다받았을 경우
dataBuffer.add((byte)0x03); //버퍼에 쌓는 부분 (마지막 etx 저장)
System.out.println("[7단계 버퍼 저장] ["+String.valueOf(dataBuffer.size())+"]");
System.out.println("[저장된 데이터 값] "+dataBuffer.toString()+"");
System.out.println("");
getDataParsing(dataBuffer); //파싱하는 곳으로 보낸다
dataBuffer.clear(); //데이터 버퍼 공간을 초기화 시켜준다
dataLen = 0; //바디 길이 초기화
break;
}
else {
dataBuffer.add(data[i]);
}
}
}
}//TODO 저장된 데이터가 있을 경우 if 종료
else { //TODO 저장된 데이터가 없을 경우 (즉, 초기 상태)
if(data[0] == (byte)0x02 && data[data.length-1] == (byte)0x03) {
dataLen = data[2]&0xff; //헤더에서 데이터길이를 저장합니다
if(data.length >= (dataLen+3)){ //초기에 들어온 데이터가 (데이터길이+헤더길이)보다 크거나 같을 경우
for(int i=0; i<(dataLen+3); i++){ //(데이터길이+헤더길이) 만큼 받는다
dataBuffer.add(data[i]); //버퍼에 쌓는 부분
}
dataBuffer.add((byte)0x03); //버퍼에 쌓는 부분 (마지막 etx 저장)
System.out.println("[1단계 버퍼 저장] ["+String.valueOf(dataBuffer.size())+"]");
System.out.println("[저장된 데이터 값] "+dataBuffer.toString()+"");
System.out.println("");
getDataParsing(dataBuffer); //파싱하는 곳으로 보낸다
dataBuffer.clear(); //데이터 버퍼 공간을 초기화 시켜준다
dataLen = 0; //바디 길이 초기화
}
}
else {
if(data[0] == (byte)0x02 && data.length > 3) { //필수 헤더 데이터가 정상적으로 들어온 경우
dataLen = data[2]&0xff; //헤더에서 데이터길이를 저장합니다
if(data.length >= (dataLen+3)){ //초기에 들어온 데이터가 (데이터길이+헤더길이)보다 크거나 같을 경우
for(int i=0; i<(dataLen+3); i++){ //(데이터길이+헤더길이) 만큼 받는다
dataBuffer.add(data[i]); //버퍼에 쌓는 부분
}
dataBuffer.add((byte)0x03); //버퍼에 쌓는 부분 (마지막 etx 저장)
System.out.println("[2단계 버퍼 저장] ["+String.valueOf(dataBuffer.size())+"]");
System.out.println("[저장된 데이터 값] "+dataBuffer.toString()+"");
System.out.println("");
getDataParsing(dataBuffer); //파싱하는 곳으로 보낸다
dataBuffer.clear(); //데이터 버퍼 공간을 초기화 시켜준다
dataLen = 0; //바디 길이 초기화
}
else{ //초기에 들어온 데이터가 데이터길이보다 작을 경우
for(int i=0; i<data.length; i++){ //전체 데이터를 다 받는다
dataBuffer.add(data[i]); //버퍼에 쌓는 부분
}
System.out.println("[3단계 버퍼 저장] ["+String.valueOf(dataBuffer.size())+"]");
System.out.println("[저장된 데이터 값] "+dataBuffer.toString()+"");
System.out.println("");
}
}
else {
System.out.println("[0단계 버퍼 저장] [STX 확인 실패 비정상 데이터]");
System.out.println("[저장된 데이터 값] []");
System.out.println("");
if(dataBuffer.size() > 0) {
dataBuffer.clear(); //데이터 버퍼 공간을 초기화 시켜준다
dataLen = 0; //바디 길이 초기화
}
}
}
}//TODO 저장된 데이터가 없을 경우 (즉, 초기 상태) 종료
}
/* =========================== */
[결과 출력]
[TCP/IP 소켓통신 및 시리얼(Serial)통신 시 사용되는 기본 데이터 수신(받은)로직 구현]
[수신된 데이터 값] [2, 49, 4, 74]
[3단계 버퍼 저장] [4]
[저장된 데이터 값] [2, 49, 4, 74]
[수신된 데이터 값] [2, 49, 4, 74, 65, 86]
[6단계 버퍼 저장] [6]
[저장된 데이터 값] [2, 49, 4, 74, 65, 86]
[수신된 데이터 값] [65, 3]
[7단계 버퍼 저장] [8]
[저장된 데이터 값] [2, 49, 4, 74, 65, 86, 65, 3]
[파싱 결과] [데이터] [JAVA]
[커맨드 1번] [정상 수행 완료]
/* =========================== */
/* =========================== */
[요약 설명]
* 1. [stx/커맨드/데이터길이/데이터/etx] - 전체 패킷 데이터 형태
[stx/커맨드/데이터길이] - 헤더 데이터 3바이트 (무조건 들어와야하는 데이터)
* 2. 경우의 수 - 데이터가 모두 한번에 정상적으로 들어온 경우
데이터가 잘려서 들어오거나, 더 많은 데이터 들어온 경우
* 3. 로직 - 데이터 들어오면 >
검증 메소드로 보내고 >
정상적으로 데이터 확인시 >
파싱 메소드로 보내고 >
파싱 메소드에서 값을 확인 후 >
다시 메인에서 알맞은 동작 수행
* 4. 사용하는 이유 - 실제로 시리얼, 소켓통신 시 데이터가 나눠서 들어오는 경우가 많아서 방지를 위함입니다
/* =========================== */
/* =========================== */
[세부 설명 - getDataConfirm() 메소드 로직]
/*[IF문 저장된 데이터가 있을 경우 로직 설명]
* 1. 먼저, dataBuffer 사이즈를 확인해 배열에 데이터가 저장되어 있는지 확인 (STX 안찾는다)
* 2. STX와 ETX값이 모두포함된경우 (즉, 다시데이터가 모두 들어온 경우) 데이터길이+헤더길이 만큼 데이터를 저장하고
마지막에 ETX를 추가해 파싱하는곳으로 보낸다
* 3. STX값만 포함되고 데이터가 적게 들어온 경우, 더많이 들어온 경우 필수 헤더데이터가 모두정상적으로 들어온지 확인하고
전체 데이터가 더 많이 들어온 경우는 데이터길이만큼 버퍼에 저장을하고 마지막에 etx를 추가해줍니다 > 파싱하는곳으로 보내고,
전체 데이터가 (데이터길이+헤더길이) 보다 작은 경우는 들어온 데이터를 모두 버퍼에 담습니다
* 4. 데이터가 적게 들어온 경우, 더많이 들어온 경우 for문을 수행하면서 들어온 데이터를 계속 받으며 저장된 버퍼 사이즈가
(데이터길이+헤더길이)가 되면 파싱하는 곳으로 보낸다
*/
/*[ELSE문 저장된 데이터가 없을 경우 로직 설명]
* 1. STX와 ETX값이 모두 포함된 경우 (즉, 정상적으로 한번에 데이터가 모두 들어온 경우) 데이터길이+헤더길이 만큼 데이터를 저장하고
마지막에 ETX를 추가해 파싱하는곳으로 보낸다
* 2. 한번에 데이터가 적게 들어온 경우, 더많이 들어온 경우는 필수 헤더 데이터가 모두 정상적으로 들어온지 확인하고
* 3. 전체 데이터가 더 많이 들어온 경우는 데이터길이만큼 버퍼에 저장을하고 마지막에 etx를 추가해줍니다 > 파싱하는곳으로 보냄
* 4. 전체 데이터가 (데이터길이+헤더길이) 보다 작은 경우는 들어온 데이터를 모두 버퍼에 담습니다
*/
/* =========================== */
/* =========================== */
[세부 설명 - getDataConfirm() 메소드 - if(dataBuffer.size() > 0) 저장된 데이터가 있을 경우]
if(data[0] == (byte)0x02 && data[data.length-1] == (byte)0x03) 부분
/*[다시 STX와 ETX값이 모두 포함된 경우 (즉, 다시 데이터가 모두 들어온 경우) 부분 설명]
* 1. 헤더에서 데이터길이를 저장합니다
* 2. 초기에 들어온 데이터가 (데이터길이+헤더길이)보다 크거나 같을 경우 (데이터길이+헤더길이) 만큼 받는다
* 3. 마지막 etx 저장하고 > 파싱하는 곳으로 보낸다
* */
else if(data[0] == (byte)0x02 && data.length > 3) 부분
/*[다시 STX값이 포함되고 데이터가 적게 들어온 경우, 더많이 들어온 경우 부분 설명]
* 1. 필수 헤더 데이터가 모두 정상적으로 들어온지 확인합니다
* 2. 데이터길이를 확인하고, 전체 데이터가 (데이터길이+헤더길이) 더한 길이와 비교를 합니다
* 3. 전체 데이터가 더 많이 들어온 경우는 데이터길이만큼 버퍼에 저장을하고 마지막에 etx를 추가해줍니다 > 파싱하는곳으로 보냄
* 4. 전체 데이터가 (데이터길이+헤더길이) 보다 작은 경우는 들어온 데이터를 모두 버퍼에 담습니다
* */
else 부분
/*[데이터가 적게 들어온 경우, 더많이 들어온 경우 부분 설명]
* 1. for문을 들어온 data 길이 만큼 반복문을 수행합니다
* 2. if 만약 데이터를 저장하다가 버퍼에 저장된 데이터 사이즈가 (데이터길이+헤더길이) 같을 경우 모든 데이터를 다 받은것으로 가정합니다
* 3. else 계속해서 버퍼에 데이터를 저장합니다
* */
/* =========================== */
/* =========================== */
[세부 설명 - getDataConfirm() 메소드 - else 저장된 데이터가 없을 경우]
if(data[0] == (byte)0x02 && data[data.length-1] == (byte)0x03) 부분
/*[STX와 ETX값이 모두 포함된 경우 (즉, 정상적으로 한번에 데이터가 모두 들어온 경우) 부분 설명]
* 1. 헤더에서 데이터길이를 저장합니다
* 2. 초기에 들어온 데이터가 (데이터길이+헤더길이)보다 크거나 같을 경우 (데이터길이+헤더길이) 만큼 받는다
* 3. 마지막 etx 저장하고 > 파싱하는 곳으로 보낸다
* */
else 부분
/*[한번에 데이터가 적게 들어온 경우, 더많이 들어온 경우 부분 설명]
* 1. 필수 헤더 데이터가 모두 정상적으로 들어온지 확인합니다
* 2. 데이터길이를 확인하고, 전체 데이터가 (데이터길이+헤더길이) 더한 길이와 비교를 합니다
* 3. 전체 데이터가 더 많이 들어온 경우는 데이터길이만큼 버퍼에 저장을하고 마지막에 etx를 추가해줍니다 > 파싱하는곳으로 보냄
* 4. 전체 데이터가 (데이터길이+헤더길이) 보다 작은 경우는 들어온 데이터를 모두 버퍼에 담습니다
* */
/* =========================== */
'Java' 카테고리의 다른 글
123. (java/자바) StringToKenizer 토큰 구분자를 사용해 문자열 분리 실시 (0) | 2021.01.15 |
---|---|
122. (java/자바) System.in.read, System.out.print 자바 표준 입출력 사용 실시 (0) | 2021.01.15 |
120. (java/자바) BigInteger 사용해 덧셈, 뺄셈, 곱셈, 나누기, 나머지, 최대공약수, 바이트값 구하기 (0) | 2021.01.13 |
119. (java/자바) MD5 사용해서 데이터 인코딩(암호화) 실시 (0) | 2021.01.13 |
118. (java/자바) SHA256 사용해서 데이터 인코딩(암호화)실시 (0) | 2021.01.13 |