Java - TLV 소켓 전송


TLV 형태로 서버 소켓에 Request하고, TLV 형태로 서버로 부터 Response 받는 예제입니다.
서버명이 MORE여서, More라는 접두어를 사용하였습니다.

TLV = Type(String, 4 byte), Length(int, 4 byte, BigEndian), Value(String, variable byte)

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.Socket;

public class MoreConnector {
    // 열거형
    public enum MoreCommand { CONV, EPDF, RECG, SPLT, ENCF, META };
    
    // 멤버
    private String m_serverIP = "127.0.0.1";
    private int m_serverPort = 2015;
    private Socket m_socket = null;

    /**
     * 생성자
     */
    public MoreConnector() {
        super();
    }
    
    /**
     * 생성자
     * @param serverIP 서버 IP
     * @param serverPort 서버 Port
     */
    public MoreConnector(String serverIP, int serverPort) {
        super();
        this.m_serverIP = serverIP;
        this.m_serverPort = serverPort;
    }
    
    /**
     * MORE 서버로 소켓 연결
     * @return 연결 성공 여부
     */
    public boolean connectSocket() {
        try {
            if(m_socket == null || m_socket.isClosed())
            {
                System.out.println("connect socket");
                m_socket = new Socket(m_serverIP, m_serverPort);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        
        return m_socket.isConnected();
    }

    /**
     * MORE 서버와의 소켓 해제
     */
    public void closeSocket() {
        try {
            System.out.println("close socket");
            m_socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * MORE 서버에 요청 후 결과를 리턴한다.
     * @param m_serverIP 서버 IP
     * @param m_serverPort 서버 Port
     * @param reqInfo 요청정보
     * @return 응답받은 TLV의 Value 문자열
     */
    public String excute(MoreCommand moreCommand, String reqInfo) throws Exception {
        DataOutputStream dos = null;
        ByteArrayOutputStream baos = null;
        
        try {
            // 소켓 점검
            if(m_socket == null || m_socket.isClosed()) 
                connectSocket();
            
            // 출력 스트림
            dos = new DataOutputStream(m_socket.getOutputStream());
            dos.write(getMoreRequest(moreCommand.toString(), reqInfo));
            
            // 입력 스트림
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            for(int s; (s=m_socket.getInputStream().read(buffer)) != -1;) {
                baos.write(buffer, 0, s);
                if(s < buffer.length) break;
            }
            byte[] resArray = baos.toByteArray();   
            
            // value만 추출
            byte[] value = new byte[resArray.length - 8];
            System.arraycopy(resArray, 8, value, 0, value.length);

            // 리턴
            return new String(value, "UTF-8");  
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            // 연결 종료
            //dos.close();
            //baos.close();
        }
    }
    

    /**
     * MORE 서버로 Request할 TLV형태의 Byte[]를 생성한다.
     * @param moreCommand MORE 엔진에서 사용하는 명령 (CONV, EPDF, RECG, SPLT)
     * @param reqInfo 명령별 요청 정보
     * @return Request할 TLV형태의 Byte[]
     */
    private byte[] getMoreRequest(String moreCommand, String reqInfo) {
        try {
            // value
            byte[] reqValue = reqInfo.getBytes("UTF-8");
            
            // type
            byte[] reqType = moreCommand.getBytes();
            
            // length
            byte[] reqLength = toBytes(reqValue.length); 
            
            // 전체 전송값
            byte[] req = new byte[reqValue.length + 8];
            System.arraycopy(reqType, 0, req, 0, 4);
            System.arraycopy(reqLength, 0, req, 4, 4);
            System.arraycopy(reqValue, 0, req, 8, reqValue.length);
            return req;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 정수를 4 byte의 big endian으로 변환한다.
     * @param i 변환할 정수값
     * @return 4 byte의 big endian
     */
    private byte[] toBytes(int i) {
        byte[] result = new byte[4];
        result[0] = (byte)(i>>24);
        result[1] = (byte)(i>>16);
        result[2] = (byte)(i>>8);
        result[3] = (byte)(i);
        return result;
    }   
}

 

광고

댓글 남기기