투케이2K

121. (java/자바) TCP/IP 소켓통신 및 시리얼(Serial)통신 시 사용되는 기본 데이터 수신(받은)로직 구현 본문

Java

121. (java/자바) TCP/IP 소켓통신 및 시리얼(Serial)통신 시 사용되는 기본 데이터 수신(받은)로직 구현

투케이2K 2021. 1. 15. 09:20

/* =========================== */

[ 개발 환경 설정 ]

개발 툴 : Eclipse

개발 언어 : Java

/* =========================== */

/* =========================== */

[전체 코드는 참고파일에서 다운받아주세요 - 코드 길이가 길어서 모두 올리지 못했습니다 ... ]

전체코드.txt
0.01MB

 

[부분 소스 코드]

	// ==== [데이터 검증 및 버퍼 저장 메소드] ====
	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. 전체 데이터가 (데이터길이+헤더길이) 보다 작은 경우는 들어온 데이터를 모두 버퍼에 담습니다

* */

/* =========================== */

반응형
Comments