네트워크
: 여러 컴퓨터들을 통신 회선으로 연결한 것LAN
: 가정, 회사, 건물, 특정 영역에 존재하는 컴퓨터를 연결한 것WAN
: LAN을 연결한 것 = 인터넷[하드웨어적 관점]ipconfig(윈도우), ifconfig(맥OS )
명령어로 네트워크 어댑터에 어떤 IP 주소가 부여되어 있는지 확인InetAddress.getLocalHost()
메소드를 호출import java.net.*;
public class InterAddressEx {
public static void main(String[] args) {
try {
InetAddress local = InetAddress.getLocalHost();
System.out.println("내 컴퓨터 ip 주소 : "+local);
InetAddress[] isArr = InetAddress.getAllByName("www.naver.com");
for(InetAddress remote : isArr)
System.out.println("www.naver.com IP주소 : "+remote.getHostAddress());
}
catch(Exception e) {}
}
}
package tcp1;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ServerEx {
private static ServerSocket serversocket = null;
public static void main(String[] args) {
System.out.println("===================");
System.out.println("서버를 종료하려면 q또는 Q를 입력하고 Enter를 입력하세요");
System.out.println("===================");
//TCP 서버 시작
startServer();
// 키보드 입력
Scanner input = new Scanner(System.in);
while(true) {
String key = input.nextLine();
if(key.toLowerCase().equals("q")) break;
}
input.close();
//TCP 서버 종료
stopServer();
}
public static void startServer() {
//작업 스레드 정의
Thread thread = new Thread() {
public void run() {
//객체 지향은 블록 단위로 코드
try {
//TCP 서버를 개발하려면 ServerSocket 생성과 Port 바인딩
// serversocket.bind(new SocketAddress(50001))로도 사용 가능
serversocket = new ServerSocket(50001);
// Port가 이미 다른 프로그램에서 사용 중이라면 BindException이 발생
System.out.println("[서버] 시작됨");
// 감시하는 리스너 필요
while(true) {
System.out.println("\n[서버]연결 요청을 기다리고 있습니다.");
//연결 수락 1:1 회선을 위해 똑같은 소켓이 필요함, 서버 소켓을 계속 감시 =>accept
// accept()는 클라이언트가 연결 요청하기 전까지 블로킹(실행 멈춘 상태) 클라이언트의 연결 요청이
// 들어오면 블로킹이 해제되고 통신용 Socket을 리턴
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();
}
public static void stopServer(){
try {
// close() 메소드를 호출해서 Port 번호를 언바이딩해야 서버 종료
serversocket.close();
System.out.println("[서버] 종료");
} catch (Exception e) {
e.printStackTrace();
}
}
}
package tcp1;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientEx {
public static void main(String[] args) {
try {
//Socket 생성과 동시에 localhost의 50001 port 연결 요청
Socket socket = new Socket("localhost", 50001);
System.out.println("[클라이언트]연결 성공");
socket.close();
System.out.println("[클라이언트]연결 끊음");
} catch (UnknownHostException e) {
//ip 표기 방법이 잘못 되었을 때 예외 처리
}catch (IOException e) {
// 해당 포트의 서버에 연결할 수 없을 경우 예외 처리
}
}
}
package tcp1;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class EchoServer {
private static ServerSocket serverSocket = null;
public static void main(String[] args) {
System.out.println("--------------------------------------------------------------------");
System.out.println("서버를 종료하려면 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();
//TCP 서버 종료
stopServer();
}
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() + "의 연결 요청을 수락함");
//-------------------------------------------------------------------------------
/*
//데이터 받기
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int readByteCount = is.read(bytes);
String message = new String(bytes, 0, readByteCount, "UTF-8");
//데이터 보내기
OutputStream os = socket.getOutputStream();
bytes = message.getBytes("UTF-8");
os.write(bytes);
os.flush();
System.out.println( "[서버] 받은 데이터를 다시 보냄: " + message);
*/
//-------------------------------------------------------------------------------
//데이터 받기
DataInputStream dis = new DataInputStream(socket.getInputStream());
String message = dis.readUTF();
//데이터 보내기
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(message);
dos.flush();
System.out.println( "[서버] 받은 데이터를 다시 보냄: " + message);
//-------------------------------------------------------------------------------
//연결 끊기
socket.close();
System.out.println("[서버] " + isa.getHostName() + "의 연결을 끊음");
}
} catch(IOException e) {
System.out.println("[서버] " + e.getMessage());
}
}
};
//스레드 시작
thread.start();
}
public static void stopServer() {
try {
//ServerSocket을 닫고 Port 언바인딩
serverSocket.close();
System.out.println( "[서버] 종료됨 ");
} catch (IOException e1) {}
}
}
package tcp1;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class EchoClient {
public static void main(String[] args) {
try {
//Socket 생성과 동시에 localhost의 50001 포트로 연결 요청;
Socket socket = new Socket("localhost", 50001);
System.out.println( "[클라이언트] 연결 성공");
//---------------------------------------------------------------------------
/*
//데이터 보내기
String sendMessage = "나는 자바가 좋아~~";
OutputStream os = socket.getOutputStream();
byte[] bytes = sendMessage.getBytes("UTF-8");
os.write(bytes);
os.flush();
System.out.println("[클라이언트] 데이터 보냄: " + sendMessage);
//데이터 받기
InputStream is = socket.getInputStream();
bytes = new byte[1024];
int readByteCount = is.read(bytes);
String receiveMessage = new String(bytes, 0, readByteCount, "UTF-8");
System.out.println("[클라이언트] 데이터 받음: " + receiveMessage);
*/
//---------------------------------------------------------------------------
//데이터 보내기
String sendMessage = "나는 자바가 좋아~~";
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
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(Exception e) {
}
}
}
일방적
으로 수신자에게 데이터를 보내는 방식. TCP처럼 연결 요청 및 수락 과정이 없기속도가 중요
하다면 UDP를 사용하고, 데이터 전달의 신뢰성이DatagramSocket
은 발신점과 수신점에 해당, DatagramPacket
은 주고받는 데이터에 해당package udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.util.Scanner;
public class NewsServer {
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();
//TCP 서버 종료
stopServer();
}
public static void startServer() {
//작업 스레드 정의
Thread thread = new Thread() {
@Override
public void run() {
try {
//DatagramSocket 생성 및 Port 바인딩
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( "[서버] 종료됨 ");
}
}
package udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class NewsClient {
public static void main(String[] args) {
try {
//DatagramSocket 생성
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) {
}
}
}
스레드풀
을 사용하는 것이 바람직package threadpool;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EchoServer {
private static ServerSocket serverSocket = null;
private static ExecutorService executorService = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
System.out.println("--------------------------------------------------------------------");
System.out.println("서버를 종료하려면 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();
//TCP 서버 종료
stopServer();
}
public static void startServer() {
//작업 스레드 정의
Thread thread = new Thread() {
@Override
public void run() {
try {
//ServerSocket 생성 및 Port 바인딩
serverSocket = new ServerSocket(50001);
System.out.println( "[서버] 시작됨\n");
//연결 수락 및 데이터 통신
while(true) {
//연결 수락
Socket socket = serverSocket.accept();
executorService.execute(() -> {
try {
//연결된 클라이언트 정보 얻기
InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
System.out.println("[서버] " + isa.getHostName() + "의 연결 요청을 수락함");
//데이터 받기
DataInputStream dis = new DataInputStream(socket.getInputStream());
String message = dis.readUTF();
//데이터 보내기
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(message);
dos.flush();
System.out.println( "[서버] 받은 데이터를 다시 보냄: " + message);
//연결 끊기
socket.close();
System.out.println("[서버] " + isa.getHostName() + "의 연결을 끊음\n");
} catch(IOException e) {
}
});
}
} catch(IOException e) {
System.out.println("[서버] " + e.getMessage());
}
}
};
//스레드 시작
thread.start();
}
public static void stopServer() {
try {
//ServerSocket을 닫고 Port 언바인딩
serverSocket.close();
executorService.shutdownNow();
System.out.println( "[서버] 종료됨 ");
} catch (IOException e1) {}
}
}
package threadpool;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NewsServer {
private static DatagramSocket datagramSocket = null;
private static ExecutorService executorService = Executors.newFixedThreadPool(10);
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();
//TCP 서버 종료
stopServer();
}
public static void startServer() {
//작업 스레드 정의
Thread thread = new Thread() {
@Override
public void run() {
try {
//DatagramSocket 생성 및 Port 바인딩
datagramSocket = new DatagramSocket(50001);
System.out.println( "[서버] 시작됨");
while(true) {
//클라이언트가 구독하고 싶은 뉴스 종류 얻기
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
datagramSocket.receive(receivePacket);
executorService.execute(() -> {
try {
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) {
}
});
}
} catch (Exception e) {
System.out.println("[서버] " + e.getMessage());
}
}
};
//스레드 시작
thread.start();
}
public static void stopServer() {
//DatagramSocket을 닫고 Port 언바인딩
datagramSocket.close();
executorService.shutdownNow();
System.out.println( "[서버] 종료됨 ");
}
}
속성
이 있으면 객체 {}
로 표기, 두 개 이상의 값
이 있으면 배열[]
로 표기{
"속성명":속성값,
"속성명":속성값,
"tel" :{"home" : "02-123-1234", "mobile" :"010-1234-1234"},
"skill" : {}
}
package json;
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;
// 회원가입에 필요한 데이터를 JSON으로 만들기
public class CreateJsonEx {
public static void main(String[] args) throws IOException{
//JSON 객체 생성 순서 상관없음
JSONObject root = new JSONObject();
//생성한 JSON객체에 단순 속성 추가
root.put("id", "winter");
root.put("name", "한바다");
root.put("age", 25);
root.put("student", true);
//생성한 JSON객체에 객체 속성 추가
JSONObject tel = new JSONObject();
tel.put("home", "02-123-1234");
tel.put("moblie", "010-1233-1234");
root.put("tel", tel);
// 배열 속성 추가
JSONArray skill = new JSONArray();
skill.put("java");
skill.put("c");
skill.put("c++");
skill.put("python");
root.put("skill", skill);
//String JSON 확인하기
String json = root.toString();
//파일로 저장
Writer writer = new FileWriter("C:/temp/member.json", Charset.forName("UTF-8"));
writer.write(json);
writer.flush();
writer.close();
}
}
RESTful API
서버 만들 시 필수라 잘 알아 둘 것package json;
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 ParseJsonEx {
public static void main(String[] args) throws IOException{
// 1. C:/temp/member.json 파일을 읽기(빨대 생성)
BufferedReader br = new BufferedReader(new FileReader("C:/Temp/member.json", Charset.forName("UTF-8")));
//2. 읽어온 내용을 String 문자열로 저장
String json = br.readLine();
//3. 빨대 제거
br.close();
// 4. 문자열에 저장된 내용에서 속성 정보를 읽어서 출력
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"));
// 5. 객체 속성 정보 읽기
JSONObject tel = root.getJSONObject("tel");
System.out.println("home : " +tel.getString("home"));
System.out.println("mobile : " +tel.getString("moblie"));
// 5. 배열 속성 정보 읽기 Obeject 타입임 조심
JSONArray skill = root.getJSONArray("skill");
System.out.println("skill : ");
for(Object s : skill) {
System.out.print(s.toString()+",");
}
System.out.println();
for(int i=0; i<skill.length(); i++) {
System.out.print(skill.get(i)+" ");
}
}
}
TCP 네트워킹을 이용해서 채팅 서버와 클라이언트를 구현
채팅 서버
ChatServer
는 채팅 서버 실행 클래스로 클라이언트의 연결 요청을 수락하고 통신용SocketClient를 생성하는 역할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;
// 채팅서버 실행 클래스 : 1) 클라이언트의 연결 요청을 수락하고 2)통신용 SocketClient를 생성한느 역할
public class ChatServer {
// 필드
ServerSocket serverSocket;
ExecutorService threadPool = Executors.newFixedThreadPool(100); // 100개의 클라이언트가 동시에 채팅 가능하도록
// chatRoom 통신용 SocketClient[비대면 공간 Map에 모여있는 느낌]를 관리하는
// 동기화(메세지가 다른 사람에게 똑같이 혹은 1: 1 채팅 가능한)된 Map
Map<String, SocketClient> chatRoom = Collections.synchronizedMap(new HashMap<>());
// 서버 시작 기능(메서드)
public void start() throws IOException {
// 서버 시작을 위해서는 서버 소켓 필요 50002 포트번호 바인드 되면서 서버 시작
serverSocket = new ServerSocket(50002);
System.out.println("[서버] 시작됨");
Thread thread = new Thread(() -> {
try { // accept()메소드로 연결이 수락된 요청에 대해서, 통신용 SocketClient를 반복해서 생성
// 무한루프
while (true) {
// 리스너 감시자 필요 : accept 필요
Socket socket = serverSocket.accept();
// 소켓을 넘겨줌
SocketClient sc = new SocketClient(this, socket);
}
} catch (IOException e) {
e.printStackTrace();
}
});
// 알아서 움직임[서버가 끝나기 전까지는 lifecycle 유지]
thread.start();
}
// 클라이언트 연결시 : SocketClient 생성 및 추가 기능(메소드)
// 채팅룸에 추가하는 메소드
public void addSocketClient(SocketClient socketClient) {
String key = socketClient.chatName + "@" + socketClient.clientIp;
chatRoom.put(key, socketClient);
System.out.println("입 장 : " + key);
System.out.println(" 현재 채팅자 수 : " + chatRoom.size() + "\n");
}
// 클라이언트 연결 종료 SocketClient 제거하는 기능(메서드)
public void removeSocketClient(SocketClient socketClient) {
String key = socketClient.chatName + "@" + socketClient.clientIp;
chatRoom.remove(key);
System.out.println("퇴 장 : " + key);
System.out.println(" 현재 채팅자 수 : " + chatRoom.size() + "\n");
}
// 모든 클라이언트들에게 메세지 보내는 기능(메서드)
public void sendToAll(SocketClient sender, String message) {
JSONObject root = new JSONObject();
root.put("clientIp", sender.clientIp);
root.put("chatName", sender.chatName);
root.put("message", message);
String json = root.toString();
Collection<SocketClient> socketClients = chatRoom.values();
// json을 보내줌 한명 한명 보내줌
for (SocketClient sc : socketClients) {
// sc는 SocketClient임 sc. 붙어있는 것은 거기 클래스에서 작업
if (sc == sender)
continue;
sc.send(json);
}
}
// 서버 종료
public void stop() {
try {
serverSocket.close();
threadPool.shutdown();
chatRoom.values().stream().forEach(sc -> sc.close());
System.out.println("[서버] 종료");
} catch (IOException e) {
// TODO: handle exception
}
}
// main도 하나의 스레드, 하나하나 실행시켜주는 메인
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();
}
}
}
단일 클래스 ChatClient
는 채팅 서버로 연결을 요청하고, 연결된 후에는 제일 먼저 대화명을 보내며 다음 서버와 메시지를 주고 받음
채팅 클라이언트 실행 클래스
ChatServer에 연결 요청
SocketClient와 1:1로 통신
package chatting;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.json.JSONObject;
// 클라이언트와 1:1 통신 역할
public class SocketClient {
//필드
ChatServer chatServer; //ChatServer()메소드를 호출하기
Socket socket; //연결을 끊을 때 필요
DataInputStream dis; // 문자열을 읽기 위한 보조 스트림
DataOutput dos; //문자열을 보내기 위한 보조 스트림
String clientIp; //클라이언트의 ip
String chatName; //클라이언트의 대화명
SocketClient(){}
SocketClient(ChatServer cs, Socket socket){
try {
this.chatServer = cs;
this.socket = socket;
// input 스트림 생성
this.dis = new DataInputStream(socket.getInputStream());
//output 스트림 생성
this.dos = new DataOutputStream(socket.getOutputStream());
// ip 얻어오기
InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
// 클라이언트 ip 넘겨주기
this.clientIp = isa.getHostName();
receive();
} catch (Exception e) {
// TODO: handle exception
}
}
//중요 : 클라이언트가 보낸 JSON 메세지를 받기 and 읽기 기능
public void receive() {
chatServer.threadPool.execute(()-> {
try {
while(true) {
String receiveJson = dis.readUTF();
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); //this란 clientsocket임
break;
case "message": //메세지
String message = jsonObject.getString("data");
chatServer.sendToAll(this, message);
break;
}
}
} catch (IOException e) {
chatServer.sendToAll(this, "나가셨습니다."); //퇴장
// chat서버 삭제
chatServer.removeSocketClient(this);
}
});
}
// JSON메소드 보내기
public void send(String json) {
try {
dos.writeUTF(json);
((DataOutputStream)dos).flush();
} catch (Exception e) {
e.printStackTrace();
}
}
// 연결 종료
public void close() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ChatClient와 1:1로 통신
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", 50002);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
System.out.println("[클라이언트] 서버에 연결됨");
}
//메소드: JSON 받기
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(Exception e1) {
System.out.println("[클라이언트] 서버 연결 끊김");
System.exit(0);
}
});
thread.start();
}
//메소드: JSON 보내기
public void send(String json) throws IOException {
dos.writeUTF(json);
dos.flush();
}
//메소드: 서버 연결 종료
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();
JSONObject jsonObject = new JSONObject();
jsonObject.put("command", "incoming");
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를 입력하고 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) {
System.out.println("[클라이언트] 서버 연결 안됨");
}
}
}
밀린 포스팅 다 올렸다!! 이제 당일에 올리는 걸 목표로 하자!! 오늘(월요일)은 휴강이다. 거의 한달 반만에 제대로 휴식 가지는 중.. 휴식하면서 회고록이랑 8월 목표 포스팅해야겠다.