22.06.13 - 네트워크에 대해 배운 날
TCP/IP 통신을 배움
TCP(Transmission Control Protocol)란?
신사적인 Protocol로 전송 제어 규약으로 데이터를 전송함에 있어서 지켜지는 약속 이다.
Web(tomcat), Database같이 서버 관련 프로그램들도 전부 TCP 기반으로 되어있다.
TCP는 동기 통신이고, UDP는 비동기 통신이다.
TCP는 왜 신사적인가?
신호를 보냈을 때 상대방과 정보를 주고 받을 때 승인 신호 절차를 거쳐서 주고받기 때문
Router란?
Hadware host간에 상호 데이터를 교환할 수 있도록 하는 장비
host1 -> router1 -> Internet -> router2 -> host2로 전달된다.
여기서 Internet은 InterNetwork의 약자로 포괄적인 통신망을 뜻한다.
Socket으로 양방향 채팅하기
필요개념 : 스레드(Thread)
스레드란?
어떠한 프로그램 내, 프로세스 내에서 실행되는 흐름의 단위
* 참고 문서
코딩교육 티씨피스쿨
4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등
tcpschool.com
양방향 채팅을 만들기 위해서는 Main Thread 1개, Working Thread 2개가 필요하다. (이는 소켓통신의 기본이다. - 멀티 스레드)
채팅은 언제 데이터가 오고 갈지 모르기 때문에 데이터 송 수신을 무한정 대기해야 한다. 하지만 메인 스레드 하나로 동작하는 방식으로는 이를 해결할 수 없다. 그러므로 메인 스레드(Main Thread)에서는 데이터 송 수신을 무한정 대기하면 안되고, 송신용, 수신용 워킹 스레드(Working Thread)를 2개 추가하여 멀티 스레드(Multi Thread) 방식으로 구현되어야 한다.
아래에 직접 개발한 코드를 보고 설명을 하겠다.
Server
MainClass.java
package main;
import java.io.*;
import java.util.*;
import threadex.ServerThread;
import java.net.*;
public class MainClass {
public static void main(String[] args) {
Socket clientSocket = null;
try {
ServerSocket serverSocket = new ServerSocket(9000);
List<Socket> list = new ArrayList<Socket>();
while (true) {
// 서버는 항상 열려있어야함
System.out.println("접속 대기중...");
clientSocket = serverSocket.accept();
list.add(clientSocket);
System.out.println("Client IP: " + clientSocket.getInetAddress() + "Port:" + clientSocket.getPort());
// 아래 부분은 접속 된 소켓을 통해 소통을 해야함 - 스레드로 이동해야함
new ServerThread(clientSocket, list).start();
}
} catch (IOException e) {
e.printStackTrace();
}
// 버전확인, binding, listen]
}
}
Server Socket을 이용하여
ThreadEx.java
package threadex;
import java.net.*;
import java.util.*;
import java.io.*;
public class ServerThread extends Thread {
Socket socket;
List<Socket> list;
public ServerThread(Socket socket, List<Socket> list) {
super();
this.socket = socket;
this.list = list;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
while (true) {
// 수신 (recv)
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = reader.readLine();
System.out.println("[받은 메시지]: " + str);
// 송신 (send)
for (Socket s : list) {
if (s != socket) {
System.out.println(s + " " + socket);
PrintWriter writer = new PrintWriter(s.getOutputStream());
writer.println(str);
writer.flush();
}
}
Thread.sleep(300);
}
} catch (Exception e) {
System.out.println("연결이 끊긴 IP: " + socket.getInetAddress());
list.remove(socket); // index뿐만 아니라 Object를 넣어도 제거가 됨
// 접속되어 있는 남아있는 클라이언트
for (Socket s : list) {
System.out.println("접속되어 있는 IP: " + s.getInetAddress() + " Port: " + s.getPort());
}
try {
socket.close(); // 종료 후 소켓 닫아주기
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
Client
MainClass.java
package main;
import java.io.*;
import java.net.*;
import java.util.*;
import threadex.ReadThread;
public class Mainclass {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 1. 접속을 해야 할 Server IP(주소)설정 - Socket
// 문지기 소켓
InetSocketAddress sockAddr = new InetSocketAddress("192.168.0.8", 9000); // 프로그램의 포트넘버가 아닌 host 자체의 포트넘버!
// 2. Socket 생성
Socket socket = new Socket();
// 3. Connect
try {
socket.connect(sockAddr, 10000);
InetAddress inetAddr;
if ((inetAddr = socket.getInetAddress()) != null) { // 서버 접속 성공
System.out.println("서버 접속 성공!");
} else {
System.out.println("서버 접속 실패!");
}
new ReadThread(socket).start();
// 4. Packet 송 수신
while (true) {
// System.out.print("[보낼 메시지]: ");
String str = sc.next();
// 송신
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.println(str);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
// 4. Packet 송수신
}
}
ReadThread.java
package threadex;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.*;
public class ReadThread extends Thread {
Socket socket;
public ReadThread(Socket socket) {
super();
this.socket = socket;
}
@Override
public void run() {
super.run();
try {
while (true) {
// 수신
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = reader.readLine();
System.out.println(str);
Thread.sleep(300); // 보내고 받을 때 대기
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
'롯데E커머스 채용연계형 교육' 카테고리의 다른 글
Socket을 활용한 채팅 프로그램 [로비, 방만들기, 채팅방 입장, 방별 채팅, 채팅방 나가기] (4) | 2022.06.15 |
---|
댓글