
⏩ 서버 : 서비스를 제공하는 프로그램
⏩ 클라이언트 : 서비스를 요청하는 프로그램
한 대의 컴퓨터에서 다양한 서버 프로그램들이 실행될 수 있는데, 클라이언트가 어떤 서버와 통신할지 선택하기 위한 번호 → IP는 네트워크 어댑터까지만 가는 정보이므로 컴퓨터 내부에서 실행되는 서버를 선택하기 위해서는 추가적인 Port 번호가 필요하다
서버는 고정적인 port번호에 바인딩, 클라이언트는 운영체제가 자동으로 부여하는 번호를 사용
| 구분명 | 범위 | 설명 |
|---|---|---|
| Well Know Port Numbers | 0 ~ 1023 | 국제인터넷주소관리기구가 특정 애플리케이션용으로 미리 예약한 Port |
| Registered Port Numbers | 1024 ~ 49151 | 회사에서 등록해 사용할 수 있는 Port |
| Dynamic Or Private Port Numbers | 49152 ~ 65535 | 운영체제가 부여하는 동적 Port 또는 개인적인 목적으로 사용할 수 있는 Port |
⏩ 자바에서 IP 주소 얻기 : java.net 패키지의 InetAddress로 표현
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Main {
public static void main(String[] args) {
try{
//local 컴퓨터의 IP주소 얻기
InetAddress local = InetAddress.getLocalHost();
System.out.println("IP address " + local.getHostAddress());
//메소드로 등록된 모든 IP주소를 배열로 저장
InetAddress[] iaArr = InetAddress.getAllByName("www.naver.com");
for(InetAddress remote : iaArr){
System.out.println("www.naver.com IP address" + remote.getHostAddress());
}
}catch (UnknownHostException e){
//예외 발생 시, 호출스택(call stack)에 있던 메소드의 정보와 예외 메시지를 화면에 출력
e.printStackTrace();
}
}
}

⏩ java.net 패키지에서 ServerSocket(클라이언트 연결을 수락하는 서버쪽 클래스)과 Socket(클-서버 양쪽에서 데이터를 주고받을 때) 클래스 사용
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Main {
private static ServerSocket serverSocket = null;
public static void main(String[] args) {
System.out.println("---------------------------------------------------------");
System.out.println("서버를 종료하려면 q 또는 Q를 입력하고 Enter 키를 입력하세요.");
System.out.println("---------------------------------------------------------");
startServer(); //TCP 서버 시작
Scanner scanner = new Scanner(System.in); //키보드 입력
while (true){
String key = scanner.nextLine();
if(key.toLowerCase().equals("q")) break;
}
scanner.close();
stopServer(); //TCP 서버 종료
}
public static void startServer() {
Thread thread = new Thread(){
@Override
public void run(){
try{
//serversocket 생성 및 Port 바인딩
serverSocket = new ServerSocket(50001);
System.out.println("[서버] 시작됨");
while (true){
System.out.println("\n[서버] 연결 요청을 기다림\n");
Socket socket = serverSocket.accept(); //연결 수락
//연결된 클라이언트 정보 얻기
InetSocketAddress isa =
(InetSocketAddress) socket.getRemoteSocketAddress();
System.out.println("[서버]"+isa.getHostName()+"의 연결 요청을 수락함");
//연결 끊기
socket.close();
System.out.println("[서버] "+isa.getHostName()+"의연결을 끊음");
}
}catch(IOException e){
System.out.println("[서버] "+e.getMessage());
}
}
};
thread.start(); //스레드 시작
}
private static void stopServer() {
try{
serverSocket.close();
System.out.println("[서버] 종료됨.");
}catch (IOException e){}
}
}
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class Main {
public static void main(String[] args) {
try{
Socket socket = new Socket("localhost",50001);
System.out.println("[클라이언트] 연결 성공");
socket.close();
System.out.println("[클라이언트] 연결 끊음");
}catch(UnknownHostException e){
//IP 표기 방법이 잘못되었을 때
} catch (IOException e) {
throw new RuntimeException(e);
// 해당 포트의 서버에 연결할 수 없는 경우
}
}
}

클라이언트가 연결 요청(connect())을 하고 서버가 연결 수락(accept())을 했다면, 양쪽의 Socket 객체로부터 입력 스트림, 출력 스트림을 얻을 수 있다
⏩ java.net 패키지에서 DatagramSocket(발신점과 수신점에 해당) 과 DatagramPacket(주고 받는 데이터) 클래스를 제공.
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.util.Scanner;
public class Main extends Thread{
private static DatagramSocket datagramSocket = null;
public static void main(String[] args) throws Exception{
System.out.println("----------------------------------------");
System.out.println("서버를 종료하려면 q를 입력하고 Enter 키를 입력하세요.");
System.out.println("----------------------------------------");
//UDP 서버 시작
startServer();
//키보드 입력
Scanner scanner = new Scanner(System.in);
while (true){
String key = scanner.nextLine();
if(key.toLowerCase().equals("q")) break;
}
scanner.close();
//UDP 서버 종료
stopServer();
}
public static void startServer() {
Thread thread = new Thread(){
@Override
public void run() {
try {
//Datagram 생성 및 포트 바인딩
datagramSocket = new DatagramSocket(50001);
System.out.println("[서버] 시작됨");
while (true){
//클라이언트가 구독하고 싶은 뉴스 주제 얻기
DatagramPacket receivePacket = new DatagramPacket
(new byte[1024],1024);
datagramSocket.receive(receivePacket);
String newsKind =
new String(receivePacket.getData(),0,
receivePacket.getLength(), "UTF-8");
//클라이언트의 IP와 Port 얻기
SocketAddress socketAddress = receivePacket.getSocketAddress();
//10개의 뉴스를 클라이언트로 송
for(int i = 1; i<=10; i++){
String data = newsKind + ": 뉴스"+i;
byte[] bytes = data.getBytes("UTF-8");
DatagramPacket sendPacket =
new DatagramPacket(bytes, 0, bytes.length, socketAddress);
datagramSocket.send(sendPacket);
}
}
} catch (Exception e) {
System.out.println("[서버]"+e.getMessage());
}
}
};
thread.start(); //스레드 시작
}
public static void stopServer() {
//datagramSocket을 닫고 port 언바인딩
datagramSocket.close();
System.out.println("[서버] 종료됨 ");
}
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class Main {
public static void main(String[] args) {
try{
//구독하고 싶은 뉴스 주제 보내기
DatagramSocket datagramSocket = new DatagramSocket();
String data = "정치";
byte[] bytes = data.getBytes("UTF-8");
DatagramPacket sendPacket = new DatagramPacket(bytes,bytes.length,
new InetSocketAddress("localhost",50001));
datagramSocket.send(sendPacket);
while (true){
//뉴스 받기
DatagramPacket receivePacket = new DatagramPacket(new byte[1024],1024);
datagramSocket.receive(receivePacket);
//문자열로 변환
String news = new String(receivePacket.getData(), 0,
receivePacket.getLength(), "UTF-8");
System.out.println(news);
//10번째 뉴스를 받으면 while 문 종료
if(news.contains("뉴스10")){
break;
}
}
//datagramSocket 닫기
datagramSocket.close();
}catch (Exception e){
}
}
}

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class EchoServer {
private static ServerSocket serverSocket = null;
private static ExecutorService executorService =
Executors.newFixedThreadPool(10);
public class Main {
private static ServerSocket serverSocket = null;
public static void main(String[] args) {
System.out.println("---------------------------------------------------------");
System.out.println("서버를 종료하려면 q 또는 Q를 입력하고 Enter 키를 입력하세요.");
System.out.println("---------------------------------------------------------");
startServer(); //TCP 서버 시작
Scanner scanner = new Scanner(System.in); //키보드 입력
while (true){
String key = scanner.nextLine();
if(key.toLowerCase().equals("q")) break;
}
scanner.close();
stopServer(); //TCP 서버 종료
}
public static void startServer() {
Thread thread = new Thread(){
@Override
public void run(){
try{
//serversocket 생성 및 Port 바인딩
serverSocket = new ServerSocket(50001);
System.out.println("[서버] 시작됨");
while (true){
System.out.println("\n[서버] 연결 요청을 기다림\n");
Socket socket = serverSocket.accept(); //연결 수락
executorService.execute(() -> {
try{
//연결된 클라이언트 정보 얻기
InetSocketAddress isa =
(InetSocketAddress) socket.getRemoteSocketAddress();
System.out.println("[서버]"+isa.getHostName()+"의 연결 요청을 수락함");
//연결 끊기
socket.close();
System.out.println("[서버] "+isa.getHostName()+"의연결을 끊음");
}
}catch(IOException e){
}
});
};
thread.start(); //스레드 시작
}
private static void stopServer() {
try{
serverSocket.close();
executorService.shutdownNow();
System.out.println("[서버] 종료됨.");
}catch (IOException e){}
}
}
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 CreateJsonExample {
public static void main(String[] args) throws IOException {
JSONObject root = new JSONObject(); //JSON 객체 생성
// 속성 추가
root.put("id","winter");
root.put("name","한겨울");
root.put("age",25);
root.put("student",true);
//객체 속성 추가
JSONObject tel = new JSONObject();
tel.put("home","02-123-1234");
tel.put("mobile","010-123-1234");
root.put("tel",tel);
//배열 속성 추가
JSONArray skill = new JSONArray();
skill.put("java");
skill.put("c");
skill.put("c++");
root.put("skill",skill);
//JSON 얻기
String json = root.toString();
System.out.println(json);
//파일로 저장
Writer writer = new FileWriter("C:/Temp/member.json", Charset.forName("UTF-8"));
writer.write(json);
writer.flush();
writer.close();
}
}
💁♂️❓파싱 : 문장을 이루고 있는 성분을 분해하고 그 분해된 성분의 위계 관계를 분석하여 구조를 결정하는 것 → 원하는 형태로 조립하고 다시 빼내는 것
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import org.json.JSONArray;
import org.json.JSONObject;
public class ParseJsonExample {
public static void main(String[] args) throws IOException {
//파일로부터 JSON 읽기
BufferedReader br = new BufferedReader(
new FileReader("C:/Temp/member.json", Charset.forName("UTF-8"))
);
String json = br.readLine();
br.close();
//JSON 파싱
JSONObject root = new JSONObject(json);
//속성 정보 읽기
System.out.println("id: "+root.getString("id"));
System.out.println("name: "+root.getString("name"));
System.out.println("age: "+root.getInt("age"));
System.out.println("student: "+root.getBoolean("student"));
//객체 속성 정보 읽기
JSONObject tel = root.getJSONObject("tel");
System.out.println("home: "+tel.getString("home"));
System.out.println("mobile: "+tel.getString("mobile"));
// 배열 속성 정보 읽기
JSONArray skill = root.getJSONArray("skill");
System.out.print ("skill: ");
for(int i = 0; i<skill.length(); i++){
System.out.print (skill.get(i)+", ");
}
}
}
이것이 자바다(신용권, 임경균 지음)