본문 바로가기
인턴

[인턴 OJT 17일차] 소켓을 활용한 주소록과 흐름

by 리잼 2023. 1. 9.
반응형

 

1. 포트번호 지정

	public static final int PORT = 50000;
 

2. 서버와 클라이언트

try (ServerSocket serverSocket = new ServerSocket(PORT)) {
			while (runFlag) {  // Flag가 True인 상태이면 계속 실행
				Socket socket = serverSocket.accept(); // 클라이언트 요청이 수신되면 받아들임

				LOGGER.debug(String.format("client connected(%s)", socket.getRemoteSocketAddress()));

				ClientSocketHandler handler = new ClientSocketHandler(socket);  // 데이터를 Thread를 상속받은 handler에서 작업한다
				handler.start();
			}
		} 
		catch (IOException e) {
			LOGGER.error(e.getMessage(), e);
		}
 

3. 소켓 생성

public SocketBookImpl(String host, int port) throws Exception {
		clientSocket = new Socket(host, port);		
		reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
		writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));	
		LOGGER.debug("==================== 소켓 생성 ================ " + clientSocket);
	}
 

4. 클라이언트에서 요청한 작업 수행

요청한 command 값을 찾아감

 

SocketBookImpl.java

	@Override
	public List<AddressBookVo> selectAddressList(AddressBookVo addressBookVo) throws Exception {
			String command = String.format("SELECT\n");
			
			writer.write(command);
			writer.flush();
			
			StringBuffer buf = new StringBuffer();
			String readLine = null;
			
			while ((readLine = reader.readLine()) != null) {	
				if (readLine.startsWith("SELECT")) {		
					buf.append(readLine + "\n");
					break;
				}
			}
			LOGGER.debug("received:" + readLine); //write한 값을 readline으로 한줄로 가져옴

			List<AddressBookVo> addressList = new ArrayList<>();
			String data[] = buf.toString().split(";");	// buf에 담긴 값들을 ; 로 나누고 data에 넣음
			
			for (String read : data) {
				LOGGER.debug("read:" + read);
				AddressBookVo address = parseCmd(read);
				addressList.add(address);
			}

			return addressList;
			
		}
 

ClientSocketHandler.java - 서버에서 데이터를 읽어오는 역할을 한다.

public void run() {
		LOGGER.debug("ClientSocketHandler run");
         // 소켓의 inputstream으로 Client가 보낸 데이터를 출력하고 한줄씩 읽기 위해 BufferedReader를 사용함
		try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));) {
			
			String readLine = null;
			while ((readLine = reader.readLine()) != null) {
				LOGGER.debug(String.format("========= readLine:%s", readLine));
				
				String[] cmdSplit = readLine.split(":"); // : 로 명령어를 구분
				
				CmdType cmd = CmdType.getCmdType(cmdSplit[KEY]); // 명령어 KEY = 0, 
				switch (cmd) {
				case SELECT:
					writer.write(handleSelect()+"\n");
					writer.flush();
					break;
				case SELECTONE:
					AddressBookVo addressBookVo = parseCmd(cmdSplit[VALUE]); // 데이터 값 VALUE = 1
					writer.write(handleOneSelect(addressBookVo));
					writer.flush();
					break;
				case INSERT:
					addressBookVo = parseCmd(cmdSplit[VALUE]);
					handleInsert(addressBookVo); 
					break;
				case UPDATE:
					addressBookVo = parseCmd(cmdSplit[VALUE]);
					handleUpdate(addressBookVo);
					break;
				case DELETE:
					addressBookVo = parseCmd(cmdSplit[VALUE]);
					handleDelete(addressBookVo);
					break;
				}
			}
		}
		catch (Exception ex) {
			LOGGER.error(ex.getMessage(), ex);
		}
		
		LOGGER.debug("ClientSocketHandler 종료");
	}
 

클라이언트가 보낸 select 요청을 소켓핸들러가 받게되고 이에 따라

case SELECT:
	writer.write(handleSelect()+"\n");
	writer.flush();
	break;
=====================================
private String handleSelect() throws Exception {
		List<AddressBookVo> addressbookList = addressBookIf.selectAddressList(new AddressBookVo());
		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append("SELECT");
		for (AddressBookVo addressBook : addressbookList) {
			stringBuffer.append(String.format("NAME=%s,BIRTHDAY=%s,GENDER=%s,PHONENUMBER=%s,ADDRESS=%s;",
												addressBook.getName(),addressBook.getBirthday(),addressBook.getGender(),
												addressBook.getPhoneNumber(),addressBook.getAddress()));
		}
		LOGGER.debug(stringBuffer.toString());
		return stringBuffer.toString();
	}
 

handleSelect가 DB명령어를 호출하고 조회 작업을 수행하게 된다..

 

작업 종료 후 소켓닫음

소켓 통신 흐름도

프로그램이 흐름도와 일치하게 작동하는 것을 확인 할 수 있었다.

무작정 코딩하지 말고 프로그램의 흐름을 파악하고 코딩 할 수 있도록 한다.

 

반응형