오늘은
오늘은 오랜만에 학원에서 수업을 들었습니다
오랜만이라 그런지 약간은 어수선한 분위기속에 수업을 한것같습니다
연휴가 길었던 만큼 다시 일상으로 회복하기가 힘들겠지만
피곤함을 이겨내려고 노력해야겠습니다
JAVA 수업
네트워크 프로그래밍
내컴퓨터(IP) > 웹(80), DBMS(1521)(포트)
- 클라이언트 = 서버 연결 요청시 IP주소와 Port를 같이 제공
- IP주소 : 127.0.0.1(localhost), 192.168.20.10
네이버 : 2223.130.195.200(www.naver.com)
- 포트번호 = 같은 컴퓨터 내에서 프로그램을 식별하는 번호
= 운영체제가 관리하는 서버 프로그램의 연결 번호
=> 서버는 시작할 때 port번호에 바인딩한다
- 0 ~ 65535
- 프로토콜 : TCP(연결이 된 상태 - 안정적인 연결), UDP(일단 보냄 - 연결이 안된 상태)
- 소켓(socket) : 데이터 송,수신, 채팅 서버
- 스레드(멀티 스레드)
Thread thread = new Thread( );
package kr.or.iei.run;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
// 필드
private static ServerSocket serverSocket;
public static void main(String[] args) {
System.out.println("==========================================");
System.out.println("서버를 종료하려면 q 또는 Q를 입력하고 Enter를 누르세요");
System.out.println("==========================================");
// TCP 서버 시작
startServer(); // 서버 호출 -> 서버 클래스 만들어야됨
Scanner scanner = new Scanner(System.in);
while(true) {
String key = scanner.nextLine();
if(key.toLowerCase().equals("q"))
break;
}
scanner.close();
stopServer(); // 서버 닫기 호출 -> 맨 아래 클래스 만듬
}
public static void startServer() {
// 항상 대기 - 스레드 필요
Thread thread = new Thread() {
@Override
public void run() {
try {
serverSocket = new ServerSocket(8000);
System.out.println("[서버] 시작됨");
// 항상 클라이언트 연결 대기
while(true) {
System.out.println("\n[서버] 연결 요청을 기다림\n");
// 연결 수락 및 클라이언트와 통신할 소켓 객체 생성
Socket socket = serverSocket.accept();
// IP 확인
InetSocketAddress isa =
(InetSocketAddress) socket.getRemoteSocketAddress();
String clientIp = isa.getHostString();
System.out.println("[서버] " + clientIp + "의 연결 요청을 수락함");
// 데이터 받기(수신)
InputStream is = socket.getInputStream(); // 항상 소켓을 통해 접근
// 기반스트림을 생성자의 매개변수로 연결
DataInputStream dis = new DataInputStream(is);
String message = dis.readUTF();
System.out.println("[서버] 데이터를 받음: " + message);
// 데이터 보내기(송신)
String message2 = "서버가 글을 보냅니다";
// OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(message2);
dos.flush();
System.out.println("[서버] 데이터를 보냄: " + message2);
socket.close();
System.out.println("[서버] " + clientIp + "의 연결을 끊음");
}
} catch (IOException e) {
//e.printStackTrace();
System.out.println("[서버] " + e.toString() + " > 연결을 끊음");
}
}
}; // thread 끝
thread.start();
}
public static void stopServer() {
try {
serverSocket.close();
System.out.println("[서버] 종료됨");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Console
==========================================
서버를 종료하려면 q 또는 Q를 입력하고 Enter를 누르세요
==========================================
[서버] 시작됨
[서버] 연결 요청을 기다림
package kr.or.iei.run;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) {
try {
// 서버에 연결 요청 및 객체 생성
Socket socket = new Socket("localhost", 8000);
System.out.println("[클라이언트] 연결 성공");
// 데이터 보내기(송신)
String sendMessage = "자바 네트워크 프로그래밍!";
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(sendMessage); // 시험
dos.flush();
System.out.println("[클라이언트] 데이터를 보냄: " + sendMessage);
// 데이터 받기(수신)
DataInputStream dis = new DataInputStream(socket.getInputStream());
String receiveMessage = dis.readUTF();
System.out.println("[클라이언트] 데이터를 받음: " + receiveMessage);
socket.close(); // 소켓 종료
System.out.println("[클라이언트] 연결 끊음");
} catch (UnknownHostException e) { // host 컴퓨터 이름이 잘못될 경우
e.printStackTrace();
} catch (IOException e) { // IP 또는 port번호에 에러가 발생한 경우
e.printStackTrace();
}
}
}
[클라이언트] 연결 성공
[클라이언트] 데이터를 보냄: 자바 네트워크 프로그래밍!
[클라이언트] 데이터를 받음: 서버가 글을 보냅니다
[클라이언트] 연결 끊음
[서버] 127.0.0.1의 연결 요청을 수락함
[서버] 데이터를 받음: 자바 네트워크 프로그래밍!
[서버] 데이터를 보냄: 서버가 글을 보냅니다
[서버] 127.0.0.1의 연결을 끊음
[서버] 연결 요청을 기다림
- 데이터 송,수신 표준
- 과거 : HTML(HyperText MarkUp Language)
-> 데이터(문서)특화 확장 언어 = XML(Extensible MarkUp Language)
- 현재 : JSON(JavaScript Object Notation) = 자바스크립트의 객체 형식을 기반으로 만들어짐
= 구조화된 형식
{ // 속성 : 속성값 => 속성을 ""쌍따옴표로 감싸야 함
"id" : "sky123",
"age" : 28,
"name" : "이하늘"
"skill" : ["Java", "sql", "C++"] // 배열
}
JSON 라이브러리
JSON 데이터를 생성(쓰기)하고, 해석(파싱, 읽기)할 수 있도록 지원해주는 프로그램
라이브러리 구하는 사이트 = 메이븐 레포지터리(Maven Repository)
json 생성 - 객체형 --> 파일로 스기(저장) : Writer -> FileWriter
json 파싱(해석) - 파일(읽기) --> 문자열 : BufferedReader -> readLine()사용
package jsondata;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import org.json.JSONArray;
import org.json.JSONObject;
public class JsonCreateExample {
public static void main(String[] args) {
// Json 데이터 만들기(생성 Create)
JSONObject member = new JSONObject();
// 속성 및 속성값 추가
member.put("id", "sky123");
member.put("name", "이하늘");
member.put("age", 28);
// 객체 속성 추가
JSONObject tel = new JSONObject();
tel.put("home", "02-123-4567");
tel.put("mobile", "010-1234-5678"); // 객체에 속성, 속성값 추가
member.put("tel", tel); // 멤버 객체에 객체 추가
// 배열 속성 추가
JSONArray skill = new JSONArray();
skill.put("java");
skill.put("C");
skill.put("C++"); // skill 배열에 추가
member.put("skill", skill); // 멤버 객체에 배열 추가
// 문자열 출력 (문자열 얻기)
String json = member.toString();
System.out.println(json);
// member 객체 출력
// System.out.println(member);
// 파일에 쓰기
try {
Writer writer = new FileWriter("C:/File/member.json",
Charset.forName("utf-8"));
writer.write(json); // json 데이터를 문자열로 쓰기
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Console
{"skill":["java","C","C++"],"name":"이하늘","tel":{"mobile":"010-1234-5678","home":"02-123-4567"},"id":"sky123","age":28}
package jsondata;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import org.json.JSONArray;
import org.json.JSONObject;
public class JsonParseExample {
public static void main(String[] args) {
try {
// 파일로부터 JSON 열기
// 보조스트림에 기반스트림 연결
Reader reader = new FileReader("C:/File/member.json");
BufferedReader br = new BufferedReader(reader);
String json = br.readLine(); // 1행 읽기
br.close();
// System.out.println(json);
// json 파싱(해석) - 문자열로 출력됨
JSONObject member = new JSONObject(json);
System.out.println("id: " + member.getString("id"));
System.out.println("name: " + member.getString("name")); // 문자형
System.out.println("age: " + member.getInt("age")); // 정수형
// 객체 속성 정보 읽기
JSONObject tel = member.getJSONObject("tel");
System.out.println("home: " + tel.getString("home"));
System.out.println("mobile: " + tel.getString("mobile"));
// 배열 속성 정보 읽기
JSONArray skill = member.getJSONArray("skill");
System.out.print("skill: ");
// for(int i = 0; i < skill.length(); i++) {
// System.out.print(skill.get(i) + ", ");
// }
for(Object obj : skill)
System.out.print(obj + ", ");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
id: sky123
name: 이하늘
age: 28
home: 02-123-4567
mobile: 010-1234-5678
skill: java, C, C++,
TCP 채팅 프로그램
- ChatServer.java
- SocketClient.java
- ChatClient.java
package chatting;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.json.JSONObject;
public class ChatServer {
// 필드
ServerSocket serverSocket;
// 스레드 풀
ExecutorService threadPool = Executors.newFixedThreadPool(100);
// 채팅방 - hashMap(싱글스레드), Hashtable(멀티스레드)
// Map<String, SocketClient> chatRoom = new Hashtable<>();
// 동기화된
Map<String, SocketClient> chatRoom =
Collections.synchronizedMap(new HashMap<>());
public void start() throws IOException{
serverSocket = new ServerSocket(6000);
System.out.println("[서버] 시작됨" );
// 항상 연결 대기 - 스레드 만들기
Thread thread = new Thread() {
@Override
public void run() {
try {
while(true) {
// 연결 수락 및 소켓 객체 생성
Socket socket = serverSocket.accept();
// 소켓 클라이언트 객체 생성
SocketClient sc = new SocketClient(ChatServer.this,socket);
}
}catch (IOException e) { // 블럭 비움
//e.printStackTrace();
}
}
};
// Thread thread = new Thread(()-> { // 람다식
//
// try {
// while(true) {
// // 연결 수락 및 소켓 객체 생성
// Socket socket = serverSocket.accept();
// // 소켓 클라이언트 객체 생성
// SocketClient sc = new SocketClient(ChatServer.this,socket);
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// });
thread.start();
}
public void addSocketClient(SocketClient socketClient) {
// key : 채팅방 이름(대화명)
String key = socketClient.chatName + "@" + socketClient.clientIp;
chatRoom.put(key, socketClient); // hashMap에 저장
System.out.println("입장: " + key);
System.out.println("현재 채팅자 수: " + chatRoom.size() + "\n");
}
// 클라이언트와 통신할 소켓 삭제
public void removeSocketClient(SocketClient socketClient) {
String key = socketClient.chatName + "@" + socketClient.clientIp;
chatRoom.remove(key); // hashMap에서 key로 삭제
System.out.println("퇴장: " + key);
System.out.println("현재 채팅자 수: " + chatRoom.size() + "\n");
}
// Json 데이터 보내기(모든 클라이언트에게 보내기)
public void sendToAll(SocketClient sender, String message) {
// json 데이터 객체 생성
JSONObject root = new JSONObject();
root.put("clientIp", sender.clientIp); // 속성, 속성값 저장
root.put("chatName", sender.chatName);
root.put("message", message);
String json = root.toString(); // 문자열 얻기
// 반복자 필요
Collection<SocketClient> socketClient = chatRoom.values();
for(SocketClient sc : socketClient) {
sc.send(json); // 문자열 보내기
}
}
public void stop() {
try {
serverSocket.close();
threadPool.shutdown();
Collection<SocketClient> socketClient = chatRoom.values();
for(SocketClient sc : socketClient) {
sc.close(); // 문자열 보내기
}
chatRoom.values();
System.out.println("[서버] 종료됨");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
ChatServer chatServer = new ChatServer();
chatServer.start();
System.out.println("==========================================");
System.out.println("서버를 종료하려면 q 또는 Q를 입력하고 Enter를 누르세요");
System.out.println("==========================================");
Scanner scanner = new Scanner(System.in);
while(true) {
String key = scanner.nextLine();
if(key.toLowerCase().equals("q")) {
break;
}
}
scanner.close();
chatServer.stop();
} catch (IOException e) {
e.printStackTrace();
}
}
}
[서버] 시작됨
==========================================
서버를 종료하려면 q 또는 Q를 입력하고 Enter를 누르세요
==========================================
package chatting;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.json.JSONObject;
public class SocketClient {
ChatServer chatServer;
Socket socket;
String clientIp;
String chatName;
DataInputStream dis;
DataOutputStream dos;
public SocketClient(ChatServer chatServer, Socket socket) {
try {
this.chatServer = chatServer;
this.socket = socket;
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
InetSocketAddress isa =
(InetSocketAddress) socket.getRemoteSocketAddress();
this.clientIp = isa.getHostString();
receive();
} catch (IOException e) {
e.printStackTrace();
}
}
// 데이터 받기(수신) : JSON 받기
public void receive() {
chatServer.threadPool.execute(() -> { // 람다식
while(true) {
try {
String receiveJson = dis.readUTF();
// JSON 파싱
// 명령(command) 속성의 구조
// {"command":"incomming", "data":"chatName"}
// {"command":"message", "data":"XXX(메시지)"}
JSONObject jsonObject = new JSONObject(receiveJson);
String command = jsonObject.getString("command");
switch(command) {
case "incomming":
this.chatName = jsonObject.getString("data");
chatServer.sendToAll(this, "입장하셨습니다");
chatServer.addSocketClient(this); // 서버의 소켓 클라이언트 생성
break;
case "message":
String message = jsonObject.getString("data");
chatServer.sendToAll(this, message);
break;
}
} catch (IOException e) {
// 클라이언트 소켓이 종료되면 연결이 끊김
chatServer.sendToAll(this, "나가셨습니다");
chatServer.removeSocketClient(this); // 서버의 소켓 클라이언트 삭제
}
}
});
} // receive 끝
// 데이터 보내기(송신) : JSON
public void send(String json) {
try {
dos.writeUTF(json);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
} // 연결이 끊길 수 있음
}
// 소켓 종료
public void close() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package chatting;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
import org.json.JSONObject;
public class ChatClient {
// 필드
Socket socket;
DataInputStream dis;
DataOutputStream dos;
String chatName;
// 연결 요청 메서드
public void connect() throws IOException{
socket = new Socket("localhost", 6000);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
System.out.println("[클라이언트] 서버에 연결됨");
}
// 데이터 송신
public void send(String json) throws IOException{
dos.writeUTF(json);
dos.flush();
}
// 데이터 수신
public void receive() {
// 항상 받을 준비
Thread thread = new Thread(()->{
try {
while(true) {
String json = dis.readUTF();
// 읽은 데이터 파싱
JSONObject root = new JSONObject(json);
String clientIp = root.getString("clientIp");
String chatName = root.getString("chatName");
String message = root.getString("message");
System.out.println("<" + chatName + "@" + clientIp + ">" + message);
}
} catch (IOException e) {
System.out.println("[클라이언트] 서버 연결 끊김");
System.exit(0); // process 완전 종료
}
});
thread.start();
}
public void unconnect() throws IOException{
socket.close();
}
public static void main(String[] args) {
try {
ChatClient chatClient = new ChatClient();
chatClient.connect();
Scanner scanner = new Scanner(System.in);
System.out.println("대화명 입력: ");
chatClient.chatName = scanner.nextLine();
// 속성 - command, data
JSONObject jsonObject = new JSONObject();
jsonObject.put("command", "incomming");
jsonObject.put("data", chatClient.chatName);
String json = jsonObject.toString(); // 객체를 문자열로 얻기
// 데이터 보냄
chatClient.send(json);
// 데이터 수신
chatClient.receive();
System.out.println("==========================================");
System.out.println("보낼 메시지를 입력하고 Enter를 누르세요");
System.out.println("서버를 종료하려면 q 또는 Q를 입력하고 Enter를 누르세요");
System.out.println("==========================================");
while(true) {
String message = scanner.nextLine();
if(message.toLowerCase().equals("q")) {
break;
}else { // 메시지 보냄
jsonObject = new JSONObject();
jsonObject.put("command", "message");
jsonObject.put("data", message);
json = jsonObject.toString();
chatClient.send(json);
}
}
scanner.close();
chatClient.unconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Console
[클라이언트] 서버에 연결됨
대화명 입력: Hi
==========================================
보낼 메시지를 입력하고 Enter를 누르세요
서버를 종료하려면 q 또는 Q를 입력하고 Enter를 누르세요
==========================================
안녕!
<Hi@127.0.0.1>안녕!
Console
입장: Hi@127.0.0.1
현재 채팅자 수: 1
JavaScript 공부
<Filter 메서드>
= 요소로 구성된 배열에서 필터링을 하거나
부분 집합을 모아 새 배열을 만드는데 쓰인다
원본 배열을 바꾸진 않는다
ex> const nums = [9, 8, 7, 6, 5, 4, 3, 2, 1];
const doos = nums.filter(n => {
return n % 2 === 1;
})
const smallNums = nums.filter(n => n < 5);
// 홀수로만 된 별도의 배열을 만든다고 가정할 때
// 콜백을 전달해서 이 콜백이 참이나 거짓을 반환해야 한다
// 그 콜백이 어떤 요소에 대해 true 값을 반환하면
// 그 요소는 필터링된 배열에 추가되는 것
ex> const movies (title, score, year) { } // 영화 배열이 있다고 가정
const goodMovies = movies.filter(movie => {
return movie.score > 80
}) // 80점 이상의 영화를 담은 배열을 반환
// 암묵적 반환 사용
const goodMovies = movies.filter(m => m.score > 80)
const badMovies = movies.filter(m => m.score < 70)
<some, every 메서드>
= 불리언 메서드 => 참, 거짓 반환 = 테스트를 하는 방법으로 사용됨
* every( )
ex> const exams = [80, 98, 92, 78, 77, 90, 89, 84, 81, 77]
// 모든 요소가 콜백으로 전달됨
exams.every(score => score >= 75) // 이 콜백 안에서 그 자체로 참이나 거짓을 반환
// exams 배열 안에서 점수 하나를 75 미만으로 낮추게 되는 경우
// 그 하나가 콜백에서 거짓을 반환 => every 전체가 거짓이 되는 것
* some( )
= every와 비슷하지만 요수 중 하나, 일부가 테스트를 통과하는지 여부를 테스트
최소 한개 이상인지만 보는 것 => 요소중에 하나라도 있다면 true, 하나도 없다면 false
<Reduce>
배열을 가져다가 점차 줄여가면서 마지막에는 결국 하나의 값만 남긴다
그 방법은 프로그래머가 정한다
자동적으로 배열 안에 있는 모든 요소를 처리하거나 하진 않는다
ex> // 두 개의 매개변수를 지닌다
[3, 5, 7, 9, 11].reduce((accumulator, currentValue) => { // accumulator = 합계 => 줄여나가야 하는 대상
return accumulator + currentValue; // currentValue = 각각의 숫자, 각각의 개별 요소
});
// 3 -> 8 -> 15 -> 24 -> 35 반환
ex> const prices = [9.99, 1.50, 19.99, 49.99, 30,50];
let total = 0;
for(let price of prices) {
total += price
}
console.log(total) // => 111.97
// reduce 사용
const total = prices.reduce((total, price) => {
return total + price
}) // total = 111.97
// 같은 결과인데 형식만 다를 뿐
// 암시적 변환 사용
const total = prices.reduce((total, price) => total + price)
배열 내에서 최대값을 찾거나 최소값을 찾는 코드를 쓸 수도 있다
ex> const prices = [9.99, 1.50, 19.99, 49.99, 30,50];
prices.reduce(min, price) => {
if (price < min) {
return price;
}
return min; // 1.50
}) // 최소값 찾기
Coding Test Practice
Description
어떤 문자열에 대해서 접미사는 특정 인덱스부터 시작하는 문자열을 의미합니다. 예를 들어, "banana"의 모든 접미사는 "banana", "anana", "nana", "ana", "na", "a"입니다. 문자열 my_string이 매개변수로 주어질 때, my_string의 모든 접미사를 사전순으로 정렬한 문자열 배열을 return 하는 solution 함수를 작성해 주세요.
function solution(my_string) {
var answer = [];
for (let i = 0; i < my_string.length; i++) {
answer.push(my_string.substring(i));
}
answer.sort()
return answer;
}
Description
정수가 담긴 배열 numbers와 문자열 direction가 매개변수로 주어집니다. 배열 numbers의 원소를 direction방향으로 한 칸씩 회전시킨 배열을 return하도록 solution 함수를 완성해주세요.
function solution(numbers, direction) {
var answer = [];
if(direction == "right"){
answer.push(numbers[numbers.length-1])
for(var i = 0; i < numbers.length-1; i++){
answer.push(numbers[i])
}
}else if(direction == "left"){
for(var i = 1; i < numbers.length; i++){
answer.push(numbers[i])
}
answer.push(numbers[0])
}
return answer;
}
Description
정수 n이 매개변수로 주어질 때, n의 약수를 오름차순으로 담은 배열을 return하도록 solution 함수를 완성해주세요.
function solution(n) {
var answer = [];
for(var i = 1; i <= n; i++){
if(n % i == 0){
answer.push(i);
}
}
return answer;
}
2023. 10. 04 (수)
프로그래머 도전기 38일차 (2) | 2023.10.06 |
---|---|
프로그래머 도전기 37일차 (0) | 2023.10.05 |
프로그래머 도전기 35일차 (2) | 2023.10.03 |
프로그래머 도전기 34일차 (0) | 2023.10.01 |
프로그래머 도전기 33일차 (2) | 2023.09.30 |