SutdaDeck() {
//1~20까지 1-10순으로 숫자 초기화 **숫자가 1,3,8의 경우 둘 중 하나는 광
int num = 1;
for (int i = 0; i < CARD_NUM; i++) {
if (i == 10) num = 1;
if (i+1 == 1 || i+1 == 3 || i+1 == 8) {
cards[i] = new SutdaCard(num++,true);
}else {
cards[i] = new SutdaCard(num++,false);
}
}//end for
}//SutdaDeck()
[남궁성님 풀이]
for (int i = 0; i < cards.length; i++){
//숫자를 넣어줄 변수
int num = i % 10 + 1; //i가 0일때 > 1, i가 1일때 >2...i가 10일때 > 1
boolean isKwang = (i < 10) && (num == 1 || num == 3 || num == 8);
cards[i] = new SutdaCard(num, isKwang);
}
엄청나게 간결해진 코드. 객체 생성자의 매개변수에 연산식을 줌으로써 코드를 확 줄였다.
▶ 내가 잡고 가야할 점 : 복잡한 조건문을 쓰기 보다, 변수 자체에 연산식을 사용하는 법을 먼저 고려해보자.
package _07_객체지향프로그래밍2;
class SutdaDeck2{
final int CARD_NUM = 20;
SutdaCard2[] cards = new SutdaCard2[CARD_NUM];
SutdaDeck2() {
//문제 7_1 정답
}//SutdaDeck()
//(1) 정의된 세개의 메서드 작성
}
class SutdaCard2{
int num;
boolean isKwang;
SutdaCard2(){
this(1,true);
}
SutdaCard2(int num, boolean isKwang){
this.num = num;
this.isKwang = isKwang;
}
@Override
public String toString() {
return num + (isKwang? "K":"");
}
}
public class EX7_2 {
public static void main(String[] args) {
SutdaDeck deck = new SutdaDeck();
System.out.println(deck.pick(0));
System.out.println(deck.pick());
deck.shuffle();
for(int i=0; i < deck.cards.length;i++)
System.out.print(deck.cards[i]+",");
System.out.println();
System.out.println(deck.pick(0));
}
}
class MyTv2 {
private boolean isPowerOn;
private int channel;
private int volume;
final int MAX_VOLUME = 100;
final int MIN_VOLUME = 0;
final int MAX_CHANNEL = 100;
final int MIN_CHANNEL = 1;
public void setIsPowerOn(boolean isPowerOn){
this.isPowerOn = isPowerOn;
}
public boolean getIsPowerOn() {
return this.isPowerOn;
}
public void setChannel(int channel) {
this.channel = channel;
}
public int getChannel() {
return this.channel;
}
public void setVolume(int volume) {
this.volume = volume;
}
public int getVolume() {
return this.volume;
}
}//end class
[남궁성님 풀이]
-- 정말 private과 getter setter만 만드는데 치중하느라 MIN과 MAX를 설정할 생각을 안했다. 함정이네 함정이야.ㅠ 그런데 현장에서도 늘 이렇게 범위를 고려해야하는 건 맞기에.. 앞으로 생각의 생각을 더 해야겠다.
입력 스트림에서 off부터 시작하여, len개를 읽어 byte 배열에 저장, 읽은 갯수를 반환
void
close()
시스템의 자원을 반환하고 입력 스트림을 닫는다. (파일)
▶ read() 메소드
InputStream is = new FileInputStream("C:/test.jpg");
int readByte;
//모든 InputStream 하위 객체 read() : 읽은 내용이 없으면 -1 반환
while((readByte = is.read()) != -1){}
▶ 키보드에서 읽어오기 : System.in
package mymain.input;
import java.io.InputStream;
public class _01_KeyboardInputTest {
public static void main(String[] args) throws Exception {
int ch;
//키보드의 입력값을 받는 inputStream
//System객체 내에 포함관계로 inputStream이 생성되어 있는 상태
InputStream is = System.in;
System.out.println("종료하려면 [Ctrl+Z]");
while((ch = is.read()) != -1) {
System.out.printf("%c",ch);
}
}
▶ 파일에서 읽어오기 : FileInputStream("파일경로")
package mymain.input;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class _02_FileInputTest {
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream("src/mymain/input/_02_FileInputTest.java");
int ch;
while((ch = is.read())!=-1) {
System.out.printf("%c",ch);
}
is.close();
}
}
▶ 네트워크에서 읽어오기 : URL(String url) > openStream()
package mymain.input;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class _03_NetWorkInputStream {
public static void main(String[] args) throws IOException {
URL url = new URL("https://www.naver.com");
InputStream is = url.openStream();
int ch;
while((ch = is.read())!=-1) {
System.out.printf("%c",ch);
}
}
}
(2) OutputStream 메서드
리턴타입
메소드
void
write()
출력 스트림으로 1byte씩 보낸다.
void
write(byte[] b)
출력 스트림에 byte[] b의 값을 보낸다.
void
write(byte[] b, int off, int len)
출력 스트림에 off부터 시작해서 len개 만큼 보낸다.
void
flush()
버퍼에 잔류하는 모든 바이트를 출력
void
close()
시스템의 자원을 반납하고 출력 스트림을 닫는다. (파일)
▶ read() 메소드
OutputStream os = new FileOutputStream("C:/test.txt");
byte[] data = "ABC".getBytes();
for(int i = 0; i < data.length; i++){
os.write(data[i]);
}
▶ 모니터로 출력하기 : System.out
package mymain.output;
import java.io.IOException;
import java.io.OutputStream;
public class _01_MonitorTest {
public static void main(String[] args) throws IOException {
OutputStream os = System.out;
//자바 -> 출력 스트림 -> 키보드버퍼로 문자를 전송
os.write(65);
String msg = "안녕";
byte[] msg_bytes = msg.getBytes();
os.write(msg_bytes);
int n = 1004;
String s = String.valueOf(n);
os.write(s.getBytes());
boolean bOk = true;
String b = String.valueOf(bOk);
os.write(b.getBytes());
//키보드 커퍼를 비우면서 콘솔로 전송
os.flush();
}
}
▶ 파일로 출력하기 : FileOutputStream("파일경로");
package mymain.output;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class _02_FileOutTest {
public static void main(String[] args) throws Exception{
OutputStream os = new FileOutputStream("a.txt");
os.write('A');
String name = "홍길동";
byte[] sArr = name.getBytes();
os.write(sArr);
int n = 1994;
os.write(String.valueOf(n).getBytes());
os.flush();
os.close();
}
}
(3) 바이트 배열 단위로 읽어오기/보내기
가. InputStream/OutputStream의 read(byte[] b), write(byte[] b) 사용
package mymain.input;
import java.io.FileInputStream;
import java.io.InputStream;
public class _04_InputStream_Array {
public static void main(String[] args) throws Exception{
InputStream is = new FileInputStream("src/mymain/input/_04_InputStream_Array.java");
int readByteNo;
byte[] readBytes = new byte[8];
// is.read(readBytes, 1, 8); <- index 1부터 8개
readByteNo = is.read(readBytes);
for(int i = 0; i < readBytes.length; i++)
System.out.printf("%c",readBytes[i]);
is.close();
}
}
package mymain.output;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class _03_OutputStream_Array {
public static void main(String[] args) throws Exception{
OutputStream os = new FileOutputStream("a2.txt");
byte[] output = "ABC".getBytes();
// os.write(output,1,2); /*: index1부터 2개*/
os.write(output);
os.close();
}
}
나. ByteArrayInputStream/ByteArrayOutputStream 객체 사용
package mymain.input;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
public class _04_InputStream_Array2 {
public static void main(String[] args) throws Exception{
byte[] inSrc = {0,1,3,4,5,6};
byte[] outSrc = null;
ByteArrayInputStream input = null;
ByteArrayOutputStream output = null;
input = new ByteArrayInputStream(inSrc);
output = new ByteArrayOutputStream();
int data = 0;
while((data = input.read()) != -1) {
output.write(data);
}
outSrc = output.toByteArray();
System.out.println("Input Source : "+Arrays.toString(inSrc));
System.out.println("Output Source : "+Arrays.toString(outSrc));
}
}
//객체 생성
InetAddress ip = InetAddres.getLocalHost();
//객체 이름, 주소 추출 : String으로 반환
String ipName = ip.getHostName();
String ipAddress = ip.getHostAddress();
[2] 도메인 이름으로 IP 주소 얻으려 할때
//도메인에서 단일 ip 주소 가져오기
InetAddress ip = InetAddress.getByName("www.naver.com");
//도메인에서 여러개의 ip주소 가져오기
InetAddress[] ipArr = InetAddress.getAllByName("www.naver.com");
package tcpProtocol;
import java.io.OutputStream;
import java.net.Socket;
public class BasicSend {
public static void main(String[] args) throws Exception{
//[1] 소켓을 연다.(연결할 서버소켓의 주소와 포트를 작성)
Socket socket = new Socket("localhost",50000);
OutputStream os = socket.getOutputStream();
for(int i = 1; i <= 3; i++) {
//[2] 소켓의 OutputStream을 통해 byte단위의 데이터를 전송한다.
String data = "데이터"+i;
os.write(data.getBytes("UTF-8"));
}
os.flush();
//[3] 소켓 연결 끊기
//socket.close(); --> 의도적인 종료 : -1 값을 전달한다.
socket.close();
}
}
[2] 수신 방법
package tcpProtocol;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class BasicAccept {
public static void main(String[] args) throws Exception{
//[1] 서버 소켓을 연다.
ServerSocket serverSocket = new ServerSocket(50000);
try {
//[2] 소켓을 연다.
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
//무한 루프로 수신 대기
System.out.println("[수신 데이터]");
while(true) {
//[3] InputStream을 통해 바이트단위 데이터를 가져온다.
byte[] byteArr = new byte[300]; //한글 3byte->100자씩 읽을 것
int len = is.read(byteArr);
if(len == -1) break;
String data = new String(byteArr,0,len,"UTF-8");
//[4] 수신 data 콘솔에 출력
System.out.println(data);
}
} catch (IOException e) {
System.out.println("[연결 종료]");
}
}
}
[연습 예제_1] TCP 1:1 전송방식으로 로컬컴퓨터에서 에코메시지 전달하기
<Client>
package tcpProtocol;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.*;
public class Client extends JFrame{
JTextArea textMonitor;
JTextField textInput;
JButton button;
Socket socket;
Client(){
/* Initial Window UI Design */
super("Chat for Client");
setLocation(300,300);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
init_UiDesign();
pack();
/* TCP Socket Communication */
init_buttonAction();
init_socket();
}//end Client()
/////////////////////////////////////////////////////
/* TCP Socket Communication Method */
private void init_buttonAction() {
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String textMessage = String.format("[사용자] %s%n", textInput.getText().trim());
if(textMessage.isEmpty()) {
JOptionPane.showMessageDialog(textMonitor,"메세지를 입력하세요.");
return;
}else {
//textMonitor.append(textMessage);
echo_message();
textInput.setText("");
return;
}
}
});
}
private void init_socket() {
try {
socket = new Socket("localhost",50000);
} catch (UnknownHostException e) {
System.out.println("해당 호스트를 찾을 수 없습니다.");
} catch (IOException e) {
System.out.println("포트가 비정상적으로 닫혀있습니다.");
}
}
protected void echo_message() {
send_message();
receive_message();
}
private void send_message() {
//send Message to server
try {
OutputStream outStream = socket.getOutputStream();
String userMessage = String.format("[사용자] %s%n", textInput.getText().trim());
//append message to Monitor
textMonitor.append(userMessage);
outStream.write(userMessage.getBytes());
outStream.flush();
} catch (IOException e) {
System.out.println("전송에 오류가 발생했습니다.");
}
}
private void receive_message() {
//receive Message from server
try {
byte[] readBytes = new byte[300];
int readNum = socket.getInputStream().read(readBytes);
String echoedMessage = new String(readBytes,0,readNum);
//append message to Monitor
textMonitor.append(echoedMessage);
} catch (IOException e) {
System.out.println("수신에 오류가 발생했습니다.");
}
}
/* UI Design Method */
private void init_UiDesign() {
//textMonitor : where chat text reveals
textMonitor = new JTextArea();
textMonitor.setBackground(new Color(0x7BC4C4));
textMonitor.setEditable(false);
JScrollPane jsp = new JScrollPane(textMonitor);
textMonitor.setPreferredSize(new Dimension(300,200));
this.add(jsp);
//textInput : where user types texts & send
JPanel jpl = new JPanel(new BorderLayout());
textInput = new JTextField();
button = new JButton("전송");
jpl.add(textInput);
jpl.add(button,"East");
this.add(jpl,"South");
}
public static void main(String[] args) {
new Client();
}//end main
}
<Server>
package tcpProtocol;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.*;
public class Server extends JFrame{
JTextArea textMonitor;
JTextField textInput;
JButton button;
ServerSocket serverSocket;
Socket socket;
Server(){
/* Initial Window UI Design */
super("Chat for Server");
setLocation(300,300);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
init_UiDesign();
pack();
/* TCP Socket Communication */
init_socket();
}//end Client()
/////////////////////////////////////////////////////
/* TCP Socket Communication Method */
private void init_socket() {
try {
serverSocket = new ServerSocket(50000);
socket = serverSocket.accept();
while(true) {
//receive Message from client
byte[] readBytes = new byte[300];
int readNum = socket.getInputStream().read(readBytes);
String[] userMessage = new String(readBytes,0,readNum).split("]");
//append message to Monitor
textMonitor.append(new String(readBytes,0,readNum));
//send Message to client
OutputStream outStream = socket.getOutputStream();
String echoedMessage = String.format("[에코]%s%n",userMessage[1]);
//append message to Monitor
textMonitor.append(echoedMessage);
outStream.write(echoedMessage.getBytes());
outStream.flush();
}
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
}
}
/* UI Design Method */
private void init_UiDesign() {
//textMonitor : where chat text reveals
textMonitor = new JTextArea();
textMonitor.setBackground(new Color(0x7BC4C4));
textMonitor.setEditable(false);
JScrollPane jsp = new JScrollPane(textMonitor);
textMonitor.setPreferredSize(new Dimension(300,200));
this.add(jsp);
//textInput : where user types texts & send
JPanel jpl = new JPanel(new BorderLayout());
textInput = new JTextField();
button = new JButton("전송");
jpl.add(textInput);
jpl.add(button,"East");
this.add(jpl,"South");
}
public static void main(String[] args) {
new Server();
}//end main
}
>>결과
8. UDP 소켓 프로그래밍
- UDP는 소포와 같이 서버소켓을 통한 연결 없이 수신, 송신만 가능한 형태이다.
- 통신 선로가 고정적이지 않음
- 데이터 손실이 발생 가능
- 대신 TCP보다는 빠르게 전송이 가능하다
이것이 자바다 참조
[1] 송신하는 법
//송신하는 법
//[1] DatagramSocket를 연다.
DatagramSocket datagramSocket = new DatagramSocket();
//만약, multi-cast방식으로 전달할 경우,
//MulticastSocket multicastSocket = new MulticastSocket();
InetAddress ia = InetAddress.getByName("localhost"); //수신되는 곳의 주소
//[2] 전달할 데이터를 패킷으로 패킹한다.
String data = "전달 데이터";
byte[] byteArr = data.getBytes("UTF-8"); //UTF-8방식으로 바이트 변환
DatagramPacket packet = new DatagramPacket(
byteArr, byteArr.length,ia,포트번호
);
//[3] DatagramSocket을 통해 패킷을 전송한다.(바이트단위로 전송된다)
datagramSocket.send(packet);
//[4] DatagramSocket을 닫아준다.
datagramSocket.close();
[2] 수신하는 법
//수신하는 법
//[1] DatagramSocket을 연다.
DatagramSocket datagramSocket = new DatagramSocket(포트번호);
//[2] 패킷을 받을 배열과 길이를 지정한다.
DatagramPacket datagramPacket = new DatagramPacket(받은 배열을 저장할 바이트 배열,배열의 길이);
//[3] 패킷을 받는다.
datagramSocket.receive(datagramPacket);
//[4] 소켓을 닫는다.
datagramSocket.close();
[연습 예제_간단한 데이터 송수신]
<Client>
package udpProtocol;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Client {
public static void main(String[] args) throws Exception{
//[1] 데이터그램 소켓으로 가야하는 곳을 지정
DatagramSocket datagramSocket = new DatagramSocket();
InetAddress ia = InetAddress.getByName("localhost");
for(int i = 1; i <= 3; i++) {
//[2] 데이터그램 패킷으로 데이터를 묶어둔다.
String data = "데이터"+i;
byte[] byteArr = data.getBytes("UTF-8");
DatagramPacket datagramPacket = new DatagramPacket(
byteArr, byteArr.length,ia,8000
);
//[3] 패킷을 소켓을 통해 전송한다.
datagramSocket.send(datagramPacket);
}//end for
//[4] 소켓을 닫는다.
datagramSocket.close();
}//end main
}
<Server>
package udpProtocol;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws Exception{
//[1] 소켓을 연다.
DatagramSocket datagramSocket = new DatagramSocket(8000);
//[2] 패킷 단위로 데이터를 받는다.
//쓰레드를 형성해서 무한 루프로 데이터를 받는다.
Thread thread = new Thread() {
@Override
public void run() {
System.out.println("수신 시작");
try {
while(true) {
DatagramPacket packet = new DatagramPacket(new byte[100],100);
datagramSocket.receive(packet);
String data = new String(packet.getData(),0,packet.getLength(),"UTF-8");
System.out.println("[받은 내용 : "+packet.getSocketAddress()+"]"+data);
}
} catch (IOException e) {
System.out.println("[수신 종료]");
}
}
};//end thread
thread.start();
Thread.sleep(10000);
datagramSocket.close();
}//end main
}
>> 수신 결과
수신 시작
[받은 내용 : /127.0.0.1:55273]데이터1
[받은 내용 : /127.0.0.1:55273]데이터2
[받은 내용 : /127.0.0.1:55273]데이터3
[수신 종료]