반응형

객체 VO를 통신으로 넘기고 싶다면 직렬화(Serialization)라는 과정을 거치고 전송 해야합니다.

직렬화를 위해선 객체가 Serializable을 상속받고 각각 고유한 serialVersionUID를 가지고 있어야하며, 각각 처리하는 VO의 패키지명과 객체명까지 일치시킬 필요성이 있습니다.

 

바로 예제를 보겠습니다.

 

VO객체를 직렬화하여 전송하기

Client

전송할 Client 부분부터 정의하겠습니다. 

TEST를 위한 BoardVO로 서버와 클라이언트의 패키지 구조를 동일하게 작성해주시고 serialVersionUID값을 꼭 맞춰줘야합니다.(VO를 덩어리로 복사하는게 속편합니다...)

 

클라이언트쪽 vo

Client vo path

 

서버쪽 vo

Server vo path

 

 

BoardVO.java

import java.io.Serializable;

public class BoardVO implements Serializable {
	
	private static final long serialVersionUID = 1234567890L;
	
	private int idx;
	private String title;
	private String content;
	private String writer;
	private String reason;

	public int getIdx() {
		return idx;
	}
	public void setIdx(int idx) {
		this.idx = idx;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getReason() {
		return reason;
	}
	public void setReason(String reason) {
		this.reason = reason;
	}
	
	@Override
	public String toString() {
		return "BoardVO [idx=" + idx + ", title=" + title + ", content=" + content + ", writer=" + writer + ", reason="
				+ reason + "]";
	}
}

 

Client2.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;

public class Client2 {
	private Socket socket;
	private ObjectOutputStream oos;
	private ObjectInputStream ois;
    
	public Client2(String ip, int port) {
		try {
			// 서버에 요청 보내기
			socket = new Socket(ip, port);
			System.out.println(socket.getInetAddress().getHostAddress() + " 연결됨");
			
			oos = new ObjectOutputStream(socket.getOutputStream());
			
			ArrayList<BoardVO> list = new ArrayList<>();
			for(int i=0; i<5; i++) {
				BoardVO vo = new BoardVO();
				vo.setTitle(i+"번째 제목입니다!");
				vo.setContent("1234567890_testtest String 문자열 테스트 컨텐츠츠츠");
				vo.setIdx(i);
				vo.setWriter("홍길동");
				list.add(vo);
			}
			
			HashMap<Object, Object> map = new HashMap<Object, Object>();
			map.put("list", list);
			//VO 메시지 발송
			oos.writeObject(map);
			oos.flush();
			
			//발송 후 메시지 받기
			ois = new ObjectInputStream (socket.getInputStream());
			// 응답 출력
			HashMap<Object, Object> returnMap = (HashMap<Object, Object>) ois.readObject();
			ArrayList<BoardVO> retrunList = (ArrayList<BoardVO>) returnMap.get("list");
			for(int i=0; i<retrunList.size(); i++) {
				System.out.println(retrunList.get(i).toString());
			}
		} catch (IOException | ClassNotFoundException e) {
		    System.out.println(e.getMessage());
		} finally {
		    // 소켓 닫기 (연결 끊기)
			try {
				if(socket != null) { socket.close();}
				if(oos != null) { oos.close(); }
				if(ois != null) { ois.close(); }
			} catch (IOException e) {
			    System.out.println(e.getMessage());
			}
		}
	}
}

BoardVO는 방금 작성했던 위치로 import처리 해주시고, 가데이터 처리 5개정도를 넣어준다음 VO객체를 발송하고 응답받는 예제입니다.

이번에는 ObjectInputStream과 ObjectOuptStream을 사용하여 객체를 발송하고 발신받는 예제입니다.

ObjectInputStream은 객체를 직렬화하여 전송하여 주고 ObjectOuptStream은 객체의 직렬화를 역직렬화 해줍니다.

해당 클래스의 readObject() 메소드는 스트림에서 객체를 읽는데 사용되며, 전송한 객체의 유형과 동일한 형태로 꼭 캐스팅을 해주어야 문제없이 파싱이 되는것을 볼 수 있습니다.

 

App.java

public class App{
    public static void main( String[] args ) {
    	String ip = "연결할 주소(ip)";
        int port = 연결할 포트;
        new Client2(ip, port);
    }
}

 

 

Server

서버에서도 동일한 VO를 사용할 예정이므로 Client쪽에서 발신하는 VO와 동일하게 패키지 구조를 구성하시고 serialserialVersionUID 또한 맞춰줍니다.

VO객체는 생성하였다고 치고 Server Socket코드를 작성하겠습니다.

 

SocketThreadServer.java

package kr.or.kisa.ktoaInterlock.socket;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.log4j.Logger;

public class SocketThreadServer extends Thread {
	
	private static final Logger logger = Logger.getLogger(SocketThreadServer.class);
	
	private Socket socket;

	public SocketThreadServer(Socket socket){
		this.socket=socket;
	}
	
	//vo형태 Serializable 데이터 넘기기
	public void run(){
		ObjectOutputStream oos = null;
		ObjectInputStream  ois = null;
		try{
			ois = new ObjectInputStream (socket.getInputStream());  
			oos = new ObjectOutputStream(socket.getOutputStream());
			
			HashMap<Object, Object> map = (HashMap<Object, Object>) ois.readObject();
			ArrayList<BoardVO> list = (ArrayList<BoardVO>) map.get("list");
			for(int i=0; i<list.size(); i++) {
				System.out.println(list.get(i).toString());
			}
			
			oos.writeObject(map);
			oos.flush();
		}catch(IOException e){
			logger.error(e);
		}catch (ClassNotFoundException e) {
			logger.error(e);
		}finally{
			try{
				if(oos != null) { oos.close();}
				if(ois != null) { ois.close();}
				if(socket != null){socket.close();}
			}catch(IOException e){
				logger.error(e);
			}
		}
	}
}

서버 코드 또한 ObjectInputStream / ObjectOutputStream 를 통해 데이터를 역직렬화하여 가져오거나 직렬화하여 넘깁니다.

 

App.java

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.apache.log4j.Logger;

import com.psw.socket.SocketThreadServer;

public class App {
	
	private static final Logger logger = Logger.getLogger(App.class);
	
	private static final int PORT_NUMBER = 4432;
	
	public static void main(String[] args) throws IOException{
		
		logger.info(":::                                                :::");
		logger.info(":::       Socket Application  Process Start        :::");
		logger.info(":::                                                :::");
		
		try(ServerSocket server = new ServerSocket(PORT_NUMBER)){
			while(true){
				Socket connection = server.accept();
				Thread task = new SocketThreadServer(connection);
				task.start();
			}
		}catch(IOException e){
			logger.error(e);
		}
	}
}

서버 코드 작성이 끝났으면 실행동작을 확인해보겠습니다.

 

 

동작 결과

서버 로그

클라이언트에서 전송받은 vo객체를 역직렬화하여 ArrayList<BoardVO>에 받고 출력 > 그대로 직렬화하여 전달한다.

 

클라이언트 로그

직렬화하여 발신한 VO 리스트를 역직렬화하여 다시 받고 출력한다.

 

반응형