이것이 자바다 - Part 19

mj·2023년 2월 3일
0
post-thumbnail

Part 19 네트워크 입출력

네트워크 기초

네트워크는 여러 컴퓨터들을 통신 회선으로 연결한 것을 말한다.
LAN은 가정, 회사, 건물, 특정 영역에 존재하는 컴푸터를 연결한 것이고, WAN은 LAN을 연결한 것이다. WAN이 우리가 흔히 말하는 인터넷이다.

서버와 클라이언트

네트워크에서 유무선으로 컴푸터가 연결되어 있다면 실제로 데이터를 주고받는 행위는 프로그램들이 한다.
서비스를 제공하는 프로그램을 일반적으로 서버라고 부르고, 서비스를 요청하는 프로그램을 클라이언트라고 부른다.

IP 주소

IP 주는 컴퓨터의 고유한 주소이다.
IP 주소는 네트워크 어댑터마다 할당된다. 만약 컴퓨터에 두 개의 네트워크 어댑터가 장착되어 있다면, 두 개의 IP 주소를 할당받을 수 있다.

Port 번호

IP는 컴퓨터의 네트워크 어댑터까지만 갈 수 있는 정보이기 때문에, 컴퓨터 내부에서 실행하는 서버를 선택하기 위해서는 추가적인 Port 번호가 필요하다.

Port는 운영체계가 관리하는 서버 프로그램의 연결 번호이다.
서버는 시작할 때 특정 Port 번호에 바인딩한다.

클라이언트도 서버에서 보낸 정보를 받기 위해서는 Port 번호가 필요한데, 서버와 같이 고정적인 Port 번호에 바인딩하는 것이 아니라 운영체제가 자동으로 부여하는 번호를 사용한다.

프로그램에서 사용할 수 있는 전체 Port 번호의 범위는 0~65535 이다.

IP 주소 얻기

자바는 IP 주소를 java.net 패키지의 InetAddress로 표현한다. InetAddress 를 이용하면 로컬 컴퓨터의 IP 주소를 얻을 수 있고, 도메인 이름으로 DNS 에서 검색한 후 IP 주소를 가져올 수도 있다.

InetAddress ia = InetAddress.getLocalHost();
InetAddress ia = InetAddress.getByName(String domainName);
InetAddress[] iaArr = InetAddress.getAllByName(String domainName);

InetAddress 객체에서 IP 주소를 얻을려면 getHostAddress() 메소드를 호출하면 된다.

String ip = InetAddress.getHostAddress();

TCP 네트워킹

IP 주소로 프로그램들이 통신할 떄 사용하는 약속된 데이터 전송 규약을 전송용 프로토콜이라고 한다.
인터넷에서 전송용 프로토콜은 TCP, UDP 가 있다.

TCP는 연결형 프로토콜로, 상대방이 연결된 상태에서 데이터를 주고 받는다.
클라이언트가 연결 요청을 하고 서버가 연결을 수락하면 통신 회선이 고정되고, 데이터는 고정 회선을 통해 전달된다.
그렇기 때문에 TCP는 보낸 데이터가 순서대로 전달되면 손실이 발생하지 않는다.

TCP는 IP와 함께 사용하기 때문에 TCP/IP 라고도 한다. TCP는 웹 브라우저가 웹 서버에 연결할 때 사용되며 이메일 전송, 파일 전송, DB 연동에도 사용된다.

자바는 TCP 네트워킁을 위해 java.net 패키지에서 ServerSocket 과 Socket 클래스를 제공하고 있다.
ServerSocket 은 클라이언트의 연결을 수학하는 서버 쪽 클래스이고, Socket은 클라이언트에서 연결 요청할 때와 클라이언트와 서버 양쪽에서 데이터를 주고 받을 때 사용되는 클래스이다.

TCP 서버

TCP 서버 프로그램을 개발하려면 우선 ServerSocket 객체를 생성해야 한다.

ServerSocket serverSocket = new ServerSocket(50001);	// Port 번호 : 50001

SeverSocket을 생성하는 또 다른 방법은 기본 생성자로 객체를 생성하고 Port 바인딩을 위해 bind() 메소드를 호출하는 것이다.

ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(50001));

만약 Port 가 이미 다른 프로그램에서 사용 중이라면 BindException 이 발생한다.

ServerSocket 이 생서되었다면 연결 요청 수학을 위해 accept() 메소드를 실행해야 한다.
accept() 는 클라이언트가 연결 요청하기 전까지 블로킹된다.
클라이언트의 연결 요청이 들어오면 블로킹이 해제되고 통신용 Socket을 리턴한다.

Socket socket = serverSocket.accept();

만약 리턴된 Socket 을 통해 연결된 클라이언트의 IP 주소와 Port 번호를 얻고 싶다면 방법은 getRemoteSocketAddress() 메소드를 호출해서 InetSocketAddress 를 얻은 다음 getHostName()과 getPort() 메소드를 호출하면 된다.

서버를 종료하려면 ServerSocket의 close() 메소드를 호출해서 Port 번호를 언바인딩시켜야 한다. 그래야 다른 프로그램에서 해당 Port 번호를 재사용할 수 있다.

serverSocket.close();

TCP 클라이언트

클라이언트가 서버에 연결 요청을 하려면 Socket 객체를 생성할 때 생성자 매개값으로 서버 IP 주소와 Port 번호를 제공하면 된다.
로컬 컴퓨터에서 실행하는 서버로 연결 요청을 할 경우에는 IP 주소 대신 localhost 를 사용할 수 있다.

Socket socket = new Socket("IP", 50001);

만약 IP 주소 대신 도메인 이름을 사용하고 싶다면, DNS에서 IP 주소를 검색할 수 있도록 생성자 매개값으로 InetSocketAddress 를 제공해야 한다.

Socket socket = new Socket( new InetSocketAddress("domainName", 50001) );

Socket 생성과 동시에 연결 요청을 하지 않고 다음과 같이 기본 생성자로 Socket 을 생성한 후 connect() 메소드로 연결 요청을 할 수도 있다.

socket = new Socket();
socket.connect( new InetSocketAddress("domainName", 50001) );

연결 요청 시 두 가지 예외가 발생할 수 있다.
UnknownHostException 은 IP 주소가 잘못 표기 되었을 떄 발생하고, IOException 은 제공된 IP와 Port 번호로 연결할 수 없을 때 발생한다.

따라서 두 가지 예외를 모두 처리해야 한다.

서버와 연결된 후에 클라이언트에서 연결을 끊고 싶다면 Socket의 close(0 메소드를 다음과 같이 호출하면 된다.

socket.close();

입출력 스트림으로 데이터 주고 받기

클라이언트가 연결 요청(connect())을 하고 서버가 연결 수락(accept())했다면, 양쪽의 Socket 객체로부터 각각 입력 스트림과 출력 스트림을 얻을 수 있다.

다음은 Socket 으로부터 InputStream과 OutputStream 을 얻는 코드이다.

InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();

상대방에게 데이터를 보낼 때에는 보낼 데이터를 byte[] 배열로 생성하고, 이것을 매개값으로 해서 OutputStream의 write() 메소드를 호출하면 된다.

String data = "보낼 데이터";
byte[] bytes = data.getBytes("UTF-8");
OutputStream os = socket.getOutputStream();
os.write(bytes);
os.flush();

데이터를 받기 위해서는 받은 데이터를 저장할 byte[] 배열을 하나 생성하고, 이것을 매개값으로 해서 InputStream의 read()메소드를 호출하면 된다.
read() 메소드는 읽은 데이터를 byte[] 배열에 저장하고 읽은 바이트 수를 리턴한다.
받는 데이터가 문자열이라면 다음과 같이 byte[] 배열을 UTF-8 로 디코딩해서 문자열로 얻을 수 있다.

byte[] bytes = new byte[1024];
InputStream is = socket.getInputStream();
int num = is.read(bytes);
String data = new String(bytes, 0, num, "UTF-8");

UDP 네트워킹

UDP 는 발신자가 일방적으로 수신자에게 데이터를 보내는 방식으로, TCP 처럼 연결 요청 및 수락 과정이 없기 때문에 TCP 보다 데이터 전송 속도가 상대적으로 빠르다.

UDP는 TCP 처럼 고정 회선이 아니라 여러 회선을 통해 데이터가 전송되기 때문에 특정 회선의 속도에 따라 데이터가 순서대로 전달되지 않거나 잘못된 회선으로 인해 데이터 손실이 발생할 수 있다.

하지만 실시간 영상 스트리밍에서 한 것의 영상이 손실되더라도 영상은 계속해서 수신되므로 문제가 되지는 않는다.

따라서 데이터 전달의 신뢰성보다 속도가 중요하다면 UDP를 사용하고, 데이터 전달의 신뢰성이 중요하다면 TCP를 사용해야 한다.

자바는 UDP 네트워킹을 위해 java.net 패키지에서 DatagramSocket과 DatagramPacket 클래스를 제공한다.
DatagramSocket은 발신점과 수신점에 해당하고, DatagramPacket은 주고 받는 데이터에 해당한다.

UDP 서버

UDP 서버를 위한 DatagramSocket 객체를 생성할 때에는 바인딩할 Port 번호를 생성자 매개값으로 제공해야 한다.

DatagramSocket datagramSocket = new DatagramSocket(50001);

UDP 서버는 클라이언트가 보낸 DatagramPacket을 항상 받을 준비를 해야 한다.
이 역할을 하는 메소드가 receive() 이다. receive() 메소드는 데이터를 수신할 때까지 블로킹되고, 데이터가 수신되면 매개값으로 주어진 DatagramPacket에 저장한다.

DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
datagramSocket.receive(receivePacket);

DatagramPacket 생성자의 첫 번째 매개값은 수신된 데이터를 저장할 배열이고, 두 번째 매개값은 수신할 수 있는 최대 바이트 수이다. 보통 첫 번째 바이트 배열의 크기를 준다.
receive() 메소드가 실행된 후 수신된 데이터와 바이트 수를 얻는 방법은 다음과 같다.

byte[] bytes = receivePacket.getData();
int num = receivePacket.getLength();

읽은 데이터가 문자열이라면 다음과 같이 String 생성자를 이용해서 문자열을 얻을 수 있다.

String data = new String(bytes, 0, num, "UTF-8");

반대로 UDP 서버가 클라이언트에게 처리 내용을 보내려면 클라이언트 IP 주소와 Port 번호가 필요한데, 이것은 receive() 로 받은 DatagramPacket 에서 얻을 수 있다.

SocketAddress socketAddress = receivePacket.getSocketAddress();

이렇게 얻은 SocketAddress 객체는 다음과 같이 클라이언트로 보낼 DatagramPacket 을 생성할 때 네 번째 매개값으로 사용된다.
DatagramPacket 생성자의 첫 번째 매개값은 바이트 배열이고 두번째는 시작 인덱스, 세 번째는 보낸 바이트 수이다.

String data = "처리 내용";
byte[] bytes = data.getBytes("UTF-8");
DatagramPacket sendPacket = new DatagramPacket( bytes, 0, bytes.length, socketAddress);

DatagramPacket 을 클라이언트로 보낸 때는 DatagramSocket의 send() 메소드를 이용한다.

datagramSocket.send( sendPacket );

더 이상 UDP 클라이언트의 데이터를 수신하지 않고 UDP 서버를 종료하고 싶을 경우에는 다음과 같이 DatagramSocket 의 close() 메소드를 호출하면 된다.

datagramSocket.close();

UDP 클라이언트

UDP 클라이언트는 서버에 요청 내용을 보내고 그 결과를 받는 역할을 한다.
UDP 클라이언트를 위한 DatagramSocket 객체는 기본 생성자로 생성한다. Port 번호는 자동으로 부여되기 때문에 따로 지정할 필요가 없다.

DatagramSocket datagramSocket = new DatagramSocket();

요청 내용을 보내기 위한 DatagramPacket을 생성하는 방법은 다음과 같다.

String data "요청 내용";
byte[] bytes = data.getBytes("UTF-8");
DatagramPacket sendPacket = new DatagramPacket(
	bytes, bytes.length, new InetSocketAddress("localhost", 50001)
);

DatagramPacket 생성자의 첫 번째 매개값은 바이트 배열이고, 두 번째 매개값은 바이트 배열에서 보내고자 하는 바이트 수이다.
세번째 매개값은 UDP 서버의 IP 와 Port 정보를 가지고 있는 InetSocketAddress 객체이다.

생성된 DatagramPacket 을 매개값으로 해서 DatagramSocket의 send() 메소드를 호출하면 UDP 서버로 DatagramPacket이 전송된다.

datagramSocket.send(sendPacket);

더 이상 UDP 서버와 통신할 필요가 없다면 DatagramSocket을 닫기 위해 close() 메소드를 다음과 같이 호출한다.

datagramSocket.close();

서버의 동시 요청 처리

일반적으로 서버는 다수의 클라이언트와 통신을 한다.
서버는 클라이언트로부터 동시에 요청을 받아서 처리하고, 처리 결과를 개별 클라이언트로 보내줘야 한다.

accept()와 receive() 를 제외한 요청 처리 코드를 별로의 스레드에서 작업하는 것이 좋은데 주의할 점은 클리이언트의 폭증으로 인한 서버의 과도한 스레드 생성을 방지해야 한다는 것이다. 그래서 스레드풀을 사용하는 것이 바람직하다.
하지만 스레트풀에서는 작업 큐의 대기 작업이 증가되어 클라이언트에서 응답을 늦게 받을 수 있다.

JSON 데이터 형식

네트워크로 전달하는 데이터가 복잡할수록 구조화된 형식이 필요하다.
네트워크 통신에서 가장 많이 사용되는 데이터 형식은 JSON(javasctript Object Notation)이다.

JSON 에서는 두 개 이상의 속성이 있는 경우에는 객체 {} 로 표기하고, 두 개 이상의 값이 있는 경우에는 배열 [] 로 표기한다.

{
  "id": "winter",
  "name": "한겨울",
  "age": 25,
  "student": true,
  "tel": { "home" : "02-1234-5678", "mobile": "010-1234-5678" },
  "skill": [ "java", "c", "c++" ]
}

JSON 을 문자열로 직접 작성할 수 있지만 대부분은 라이브러리를 이용해서 생성한다.

다음은 JSON 표기법과 관련된 클래스들이다.

클래스용도
JSONObjectJSON 객체 표기를 생성하거나 파싱할 때 사용
JSONArrayJSON 배열 표기를 생성하거나 파싱할 때 사용

JSON에서 속성 순서는 중요하지 않기 때문에 추가한 순서대로 작성되지 않아도 상관없다.
그리고 줄바꿈 처리가 되지 않는데, 오히여 네트워크 전송량을 줄여주기 때문에 더 좋다.

문제

  1. 서버와 클라이언트에 대한 설명으로 틀린 것은 무엇입니까?
    ➊ 서비스를 제공하는 쪽이 서버이고, 서비스를 요청하는 쪽이 클라이언트이다.
    ➋ 클라이언트가 서버에 연결하기 위해서는 IP 주소만 있으면 된다.
    ➌ 포트(Port)는 여러 서버 중에 특정 서버와 연결하기 위해 필요한 정보다.
    ➍ 서버와 클라이언트는 양쪽 모두 포트가 배정되어야 한다.
  • 답 : ➋
  1. TCP와 UDP에 대한 설명으로 틀린 것을 모두 선택하세요.
    ➊ TCP는 데이터 입출력에 앞서 연결 요청과 수락 과정이 필요하다.
    ➋ TCP는 여러 회선으로 데이터를 전달하므로, 데이터의 전달 순서가 달라질 수 있다.
    ➌ UDP는 연결 수락 과정이 없기 때문에 TCP보다 상대적으로 빠르다.
    ➍ UDP는 고정된 회선으로 데이터를 전달하기 때문에 전달 신뢰도가 높다.
  • 답 : ➋, ➍
  1. 다음은 TCP 클라이언트가 서버로 연결 요청을 하고 서버는 연결을 수락하는 코드이다. 빈칸에 들
    어갈 코드를 작성하세요. (단, 클라이언트와 서버는 같은 컴퓨터에서 실행하고 있습니다.)
  • 답 :
new Socket("localhost", 5001);
serverSocket.accept()
  1. TCP를 사용하는 클라이언트를 서버에 연결해 Socket으로 데이터 입출력을 하려고 합니다. 빈칸
    에 Socket을 통해 얻는 입출력 스트림의 타입을 적어보세요.
  • 답 :
InputStream,  OutputStream
OutputStream,  InputStream
  1. UDP를 사용하는 클라이언트를 서버에서 사용되는 클래스 이름 및 데이터와 수신·발신할 때, 사
    용되는 클래스 이름을 ①~⑤ 빈칸에 작성해보세요.
  • 답 :
1. DatagramSocket 
2. DatagramPacket 
3. DatagramSocket 
4. DatagramPacket
5. DatagramPacket
  1. 서버 측 DatagramSocket에 대한 설명으로 틀린 것은 무엇입니까?
    ➊ 서버에서는 고정된 Port 번호를 제공하고 생성해야 한다.
    ➋ receive() 메소드는 데이터를 수신할 때까지 블로킹된다.
    ➌ 클라이언트의 IP 주소와 Port 번호는 수신된 DatagramPacket에서 얻을 수 있다.
    ➍ 클라이언트로 DatagramPacket을 발신할 때 write() 메소드를 사용한다.
  • 답 : ➍
  1. 상품 관리 프로그램을 TCP를 이용해서 개발하려고 합니다. 다음 내용에 맞게 서버와 클라이언트
    를 직접 개발해보세요.




  • 답 :
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok. NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
	private int no;
	private String name;
	private int price;
	private int stock;
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.json.JSONArray;
import org.json.JSONObject;
public class ProductServer {
	private ServerSocket serverSocket;
	private ExecutorService threadPool;
	private List<Product> products;
	private int sequence;

	public void start() throws IOException {
 		serverSocket = new ServerSocket(50001);
 		threadPool = Executors.newFixedThreadPool(100);
 		products = new Vector<Product>();
 		System.out.println( "[서버] 시작됨");
 		while(true) {
 			Socket socket = serverSocket.accept();
			SocketClient sc = new SocketClient(socket);
 		}
	}

	public void stop() {
 		try {
 			serverSocket.close();
 			threadPool.shutdownNow();
 			System.out.println( "[서버] 종료됨 ");
 		} catch (IOException e1) {}
	} 

	public class SocketClient {
 		private Socket socket;
 		private DataInputStream dis;
 		private DataOutputStream dos;

 		public SocketClient(Socket socket) {
 			try {
 				this.socket = socket;
 				this.dis = new DataInputStream(socket.getInputStream());
 				this.dos = new DataOutputStream(socket.getOutputStream()); 
 				receive();
 			} catch(IOException e) {
 				close();
 			}
 		}

 		public void receive() {
 			threadPool.execute(() -> {
 				try {
 					while(true) {
 						String receiveJson = dis.readUTF(); 
 						JSONObject request = new JSONObject(receiveJson);
 						int menu = request.getInt("menu");
 						switch(menu) {
 							case 0 -> list(request);
 							case 1 -> create(request);
 							case 2 -> update(request);
 							case 3 -> delete(request);
 						}
 					}
 				} catch(IOException e) {
 					close();
 				}
 			});
 		}

 		public void list(JSONObject request) throws IOException {
 			JSONArray data = new JSONArray();
 			for(Product p : products) {
 				JSONObject product = new JSONObject();
 				product.put("no", p.getNo());
 				product.put("name", p.getName());
 				product.put("price", p.getPrice());
 				product.put("stock", p.getStock());
 				data.put(product);
 			} 
 			JSONObject response = new JSONObject();
 			response.put("status", "success");
 			response.put("data", data);
 			dos.writeUTF(response.toString());
 			dos.flush();
 		}

 		public void create(JSONObject request) throws IOException {
 			JSONObject data = request.getJSONObject("data");
 			Product product = new Product();
 			product.setNo(++sequence);
 			product.setName(data.getString("name"));
 			product.setPrice(data.getInt("price"));
 			product.setStock(data.getInt("stock"));
 			products.add(product);
 			JSONObject response = new JSONObject();
 			response.put("status", "success");
 			response.put("data", new JSONObject());
 			dos.writeUTF(response.toString());
 			dos.flush();
 		}

 		public void update(JSONObject request) throws IOException {
 			JSONObject data = request.getJSONObject("data");
 			int no = data.getInt("no");
 			for(int i= 0; i<products.size(); i++) {
 				Product product = products.get(i);
 				if(product.getNo() = = no) {
 					product.setName(data.getString("name"));
 					product.setPrice(data.getInt("price"));
 					product.setStock(data.getInt("stock"));
 				}
 			}
   			JSONObject response = new JSONObject();
 			response.put("status", "success");
 			response.put("data", new JSONObject());
 			dos.writeUTF(response.toString());
 			dos.flush();
 		}

 		public void delete(JSONObject request) throws IOException {
 			JSONObject data = request.getJSONObject("data");
 			int no = data.getInt("no");
 			Iterator<Product> iterator = products.iterator();
 			while(iterator.hasNext()) {
 				Product product = iterator.next();
 				if(product.getNo() = = no) {
 					iterator.remove();
 				}
 			}
 			JSONObject response = new JSONObject();
 			response.put("status", "success");
 			response.put("data", new JSONObject());
 			dos.writeUTF(response.toString());
 			dos.flush();
 		}

 		public void close() {
 			try {
 				socket.close();
 			} catch(Exception e) {}
 		}
	}

	public static void main(String[] args) {
 		ProductServer productServer = new ProductServer();
 		try {
 			productServer.start();
 		} catch(IOException e) {
 			System.out.println(e.getMessage());
 			productServer.stop();
 		}
	}
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
import org.json.JSONArray;
import org.json.JSONObject;
public class ProductClient {
	private Socket socket;
	private DataInputStream dis;
	private DataOutputStream dos;
	private Scanner scanner;
	public void start() throws IOException {
 		socket = new Socket("localhost", 50001);
 		dis = new DataInputStream(socket.getInputStream());
 		dos = new DataOutputStream(socket.getOutputStream());
 		System.out.println("[클라이언트] 서버에 연결됨");	 	
 		scanner = new Scanner(System.in);
 		list();
	}
	public void stop() {
 		try {
 			socket.close();
 			scanner.close();
 		} catch(Exception e) {}
 		System.out.println("[클라이언트] 종료됨");
	}

	public void menu() throws IOException {
 		System.out.println();
 		System.out.println("---------------------------------------------------------------");
 		System.out.println("메뉴: 1.Create | 2.Update | 3.Delete | 4.Exit");
 		System.out.print("선택: ");
 		String menuNo = scanner.nextLine();
 		System.out.println(); 
 		switch(menuNo) {
 			case "1" -> create();
 			case "2" -> update();
 			case "3" -> delete();
 			case "4" -> exit();
 		}
	}

	public void list() throws IOException{
		System.out.println();
 		System.out.println("[상품 목록]");
 		System.out.println("---------------------------------------------------------------");
 		System.out.printf("%-6s%-30s%-15s%-10s\n", "no", "name", "price", "stock");
 		System.out.println("---------------------------------------------------------------");
 		JSONObject request = new JSONObject();
 		request.put("menu", 0);
 		request.put("data", new JSONObject());
 		dos.writeUTF(request.toString());
 		dos.flush();
 		JSONObject response = new JSONObject(dis.readUTF());
 		if(response.getString("status").equals("success")) {
	 		JSONArray data = response.getJSONArray("data");
 			for(int i=0; i<data.length(); i++) {
 				JSONObject product = data.getJSONObject(i);
 				System.out.printf(
 					"%-6d%-30s%-15d%-10d\n",
 					product.getInt("no"),
 					product.getString("name"),
 					product.getInt("price"),
 					product.getInt("stock")
 				);
 			}
 		}
 		menu();
	}

	public void create() throws IOException {
		System.out.println("[상품 생성]");
 		Product product = new Product();
 		System.out.print("상품 이름: ");
 		product.setName(scanner.nextLine());
 		System.out.print("상품 가격: ");
 		product.setPrice(Integer.parseInt(scanner.nextLine()));
 		System.out.print("상품 재고: ");
 		product.setStock(Integer.parseInt(scanner.nextLine()));
 		JSONObject data = new JSONObject();
 		data.put("name", product.getName());
 		data.put("price", product.getPrice());
 		data.put("stock", product.getStock());
 		JSONObject request = new JSONObject();
 		request.put("menu", 1);
 		request.put("data", data);
 		dos.writeUTF(request.toString());
 		dos.flush();
 		JSONObject response = new JSONObject(dis.readUTF());
 		if(response.getString("status").equals("success")) {
 			list();
 		}
	}

	public void update() throws IOException {
		System.out.println("[상품 수정]");
 		Product product = new Product();
 		System.out.print("상품 번호: ");
 		product.setNo(Integer.parseInt(scanner.nextLine())); 
 		System.out.print("이름 변경: ");
 		product.setName(scanner.nextLine());
 		System.out.print("가격 변경: ");
 		product.setPrice(Integer.parseInt(scanner.nextLine()));
 		System.out.print("재고 변경: ");
 		product.setStock(Integer.parseInt(scanner.nextLine()));
 		JSONObject data = new JSONObject();
 		data.put("no", product.getNo());
 		data.put("name", product.getName());
 		data.put("price", product.getPrice());
 		data.put("stock", product.getStock()); 
 		JSONObject request = new JSONObject();
 		request.put("menu", 2);
 		request.put("data", data);
 		dos.writeUTF(request.toString());
 		dos.flush();
 		JSONObject response = new JSONObject(dis.readUTF());
 		if(response.getString("status").equals("success")) {
 			list();
 		} 
	}

	public void delete() throws IOException {
		System.out.println("[상품 삭제]");
 		System.out.print("상품 번호: ");
 		int no = Integer.parseInt(scanner.nextLine());
 		JSONObject data = new JSONObject();
 		data.put("no", no);
 		JSONObject request = new JSONObject();
 		request.put("menu", 3);
 		request.put("data", data);
 		dos.writeUTF(request.toString());
 		dos.flush();
 		JSONObject response = new JSONObject(dis.readUTF());
 		if(response.getString("status").equals("success")) {
 			list();
 		}
	}

	public void exit() {
 		stop();
	}

	public static void main(String[] args) { 
 		ProductClient productClient = new ProductClient();
 		try {
 			productClient.start();
 		} catch(IOException e) {
 			System.out.println(e.getMessage());
 			productClient.stop();
 		}
	}
}
profile
사는게 쉽지가 않네요

0개의 댓글