Programing/Network

JAVA Socket 자바 소켓통신 바이트 데이터 주고 받기 c언어

리커니 2017. 2. 28.
반응형

 

JAVA Socket 자바 소켓통신 바이트 데이터 주고 받기

 

이번 포스팅은 장비 또는 서버와의 통신을 하는 방법에 대해

간단한 예제로 알아보려 합니다.

 

소켓으로 서버와 연결 하고, 데이터를 보내고, 보낸 데이터에 대한 응답을 받아 처리하는 방법에 대해 알아보겠습니다.

 

가장 먼저 Socket 클래스를 사용하여 원하는 장비 혹은 서버와 연결 요청을 합니다.

 

Socket socket = new Socket("ip주소", 포트);

socket.setSoTimeout(5000);

 

ip주소는 String, 포트는 int 형 입니다.

그리고 해당 서버나 장비에서 응답이 없을 경우 연결을 끊는 소스를 추가 합니다. (5초)

 

이제 데이터를 보내고 받을 스트림을 선언합니다.

 

OutputStream os = socket.getOutputStream();

DataOuputStream dos = new DataOutputStream(os);

 

InputStream is = socket.getInputStream();

DataInputStream dis = new DataInputStream(is);

    

이제 서버와 연결을 했고, 서버로 부터 데이터를 주고 받을 준비가 되었습니다.

 

서버와의 통신을 하기 위한 프로토콜 정의서 를 확인하여 header, body, tail 의 데이터를 만들어줍니다.

간단히 바이트 배열을 선언하고 프로토콜 정의서의 내용에 맞게 데이터를 넣어주면 됩니다.

 

예를 들어 전체 보낼 데이터의 크기가 10byte이고

HEADER내용이 아래와 같다면

STX (0x02) 1byte,

OPCODE (0x23) 1byte,

Length (Body의 길이) 2byte

 

try{

sendData = new byte[10];

sendData[0] = (byte)0x02;

sendData[1] = (byte)0x23;

byte[] bodySize;

bodySize = intToByteArray(4, 2);

sendData[2] = (byte)bodySize[0];

sendData[3] = (byte)bodySize[1];

                    .

                    .

                   

이런 식으로 바이트 배열에 넣어서 보낼 데이터를 만들면 됩니다.

intToByteArray와 같이 자바에서 각종 바이트 변환 함수는 아래의 Link를 참조합니다.

 

Link : java 자바 byte 형변환 함수 정리

 

 

프로토콜정의서에 정의된 sendData를 만들었다면 이제 서버로 보내야겠죠.

 

try{

dos.write(sendData);

dos.flush();

 

DataOutputStream의 write 메소드로 소켓에 연결된 서버에 데이터를 보내고

DataOutputStream을 비우는(flush) 부분입니다.

 

데이터를 정확하게 보냈다면 이제 서버로 부터 응답이 올것입니다.

여기서 주의해야될 것이 있습니다.

 

보통 1024byte 이하의 데이터는 한번에 받을 수 있지만,

통신회선에 따라 데이터를 특정 바이트 만큼 잘라서 여러번에 걸쳐 보내기 때문에 반복해서

원하는 데이터 크기 만큼 받아야 한다는 것입니다.

 

만약에 10000byte를 서버에서 보낸다면, 1000byte, 980byte.....이런식으로 잘라 보낸다는 것이죠.

 

그래서 보통 많은 데이터를 주고 받을 때는 해더에 바디 데이터의 크기를 포함해서 보내게 됩니다.

그래야 보낸 데이터를 다 받았는지 아닌지를 판단 할 수 있기 때문입니다.

 

byte[] reciveData = null;
byte[] headerBuffer = new byte[4];
dis.read(headerBuffer);

 

byte[] lengthChk = new byte[2];
lengthChk[0] = headerBuffer[2];
lengthChk[1] = headerBuffer[3];

int returnLength = byteArrayToInt(lengthChk, 2);

 

ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read;
reciveData = new byte[returnLength];   //헤더의 데이터 크기 만큼 바이트 배열 생성

 

 

 

//한번에 많은 데이터를 받을 수 없으므로 헤더에서 보내온 데이터 크기만큼 while문을 돌면서 받고

다 받았다면 break;

while((read = dis.read(reciveData, 0, reciveData.length))!= -1){
    buffer.write(reciveData, 0 , read);
    returnLength = returnLength-read;
    if (returnLength<=0){
        break;

    }
}


buffer.flush();

 

그래서 위와 같이 데이터의 헤더 부분만 받아 전체 데이터의 크기를 확인하고

그만큼의 바이트 배열을 생성하는 것입니다.

 

}catch (Exception e){

e.printStackTrace();

}

 

} finally {

dos.close();

dis.close();

docket.close();

System.out.println("소켓 연결 종료");

}

 

마지막으로 finally 구분에서 모든 스트림과 소켓을 닫아 줍니다.

 

여러번 해보면 간단한 노가다(?!) 작업이지만,  처음에는 막막할 수 있습니다.

이번 포스팅으로 그런 막막함이 좀 가셨으면 좋겠네요 ㅎ

반응형

댓글

💲 추천 글