반응형
TCPServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TCPServer implements Runnable {
private static Socket clientSocket; // 각각의 클라이언트를 구분하기 위함
static PrintWriter out = null;
static ArrayList<Socket> list = new ArrayList<Socket>(); // 클라이언트 쓰레드를 담을 ArrayList 생성
static int UserNum = 0; // 서버에서 클라이언트에게 번호를 부여하기 위한 변수
public TCPServer(Socket clientSocket) { // 멀티 쓰레드 환경을 구축하기 위한 생성자. 각각의 개별 쓰레드를 생성
this.clientSocket = clientSocket;
list.add(clientSocket); // 쓰레드들을 리스트에 추가하는 부분
}
public static void main(String[] args) {
ExecutorService eService = Executors.newFixedThreadPool(5);
// 쓰레드 생성. 6번째 접속부터는 BLOCKING-참가자를 6명으로 제한
System.out.println("#서버 시작");
try (ServerSocket sSocket = new ServerSocket(10000)) {
// try-with-resource문 사용 시 자동으로 자원 해제
while (true) { // 접속하는 클라이언트들에게 무한 서비스
System.out.println("#연결 대기 중 ......");
clientSocket = sSocket.accept();
// 연결 수락. client 연결정보, ip주소 담음
TCPServer tes = new TCPServer(clientSocket);
// 개별 쓰레드 객체 생성. 연결 수락시 접속한 클라이언트의 정보 담김
// new Thread(tes).start();
// 각각의 쓰레드가 식별가능한 인수를 갖게 된다, 개별적인 수행으로 효율적이지는 않다
eService.submit(tes);
// 더 효율적인 방법
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("#서버 종료");
eService.shutdown();
}
public void run() {
// 각각의 클라이언트들에 대한 피드백을 하는 run함수
// 접속한 클라이언트들에 대응가능한 송수신용 버퍼와 각종 변수들이 들어있음
try {
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// 수신 버퍼
// OutputStream : 서버에서 클라이언트로 메세지 보내기
OutputStream out = clientSocket.getOutputStream();
PrintWriter writer = new PrintWriter(out, true);
// out = new PrintWriter(clientSocket.getOutputStream(), true); //송신 버퍼
UserNum++;
System.out.println("#클라이언트 : " + UserNum + "(" + Thread.currentThread() + ")" + " 연결됨!");
String UserID = br.readLine(); // 사용자에게서 id를 입력받아 설정
String inputLine; // 클라이언트가 보낸 값 저장
writer.println("#[" + UserID + "]님이 접속하셨습니다.");
System.out.println("#[" + UserID + "]님이 접속하셨습니다.");
while ((inputLine = br.readLine()) != null) {
// readLine(): client가 보낸 msg를 br에서 한줄씩 꺼냄
// System.out.println("[" + UserID + "] " + inputLine);
// 클라이언트에게서 받아온 정보를 한줄씩 출력
for (int i = 0; i < list.size(); i++) {
// ArrayList의 사이즈만큼 for문을 돌리면서 모든 클라이언트에게 메시지 전송
out = list.get(i).getOutputStream();
// ArrayList의 i번째 getOutputStream()요소를 가져와 out객체에 대입한다.
writer = new PrintWriter(out, true);
// 새로운 printWriter객체를 생성
writer.println("[" + UserID + "] " + inputLine);
// ArrayList의 i번째 요소를 클라이언트에게 송신한다.
}
}
out.close();
System.out.println("#클라이언트 : " + Thread.currentThread() + " 종료됨!");
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
TCPClient.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class TCPClient {
Socket cSocket;
BufferedReader br;
PrintWriter out;
Scanner scv;
public TCPClient() { // 메시지 송신
System.out.println("서버에 접속하는 중입니다.");
try {
// accept() 호출 후 쓰레드 만들어지고, Array List에 추가된다.
InetAddress localAddress = InetAddress.getLocalHost();
cSocket = new Socket(localAddress, 10000);// Socket cSocket = new Socket("127.0.0.1", 9000);
// 10000번 포트와 로컬 주소를 사용하는 cSocket이라는 새로운 소켓을 생성
SocketThread st = new SocketThread(); // 소켓 쓰레드의 새로운 객체인 st라는 쓰레드를 생성한다.
st.start(); // st를 실행시킨다.
// Test클래스가 Thread 클래스를 상속했다.
// Thread 클래스의 run 메소드를 구현하면 st.start() 실행 시 st객체의 run 메소드가 수행이 된다.
out = new PrintWriter(cSocket.getOutputStream(), true);
scv = new Scanner(System.in);
// 사용자 아이디 지정하는 부분
String UserID = "";
System.out.println("#서버에 연결됨!");
System.out.println("#사용할 ID를 입력해주세요.");
out.print(UserID);
while (true) {
String inputLine = scv.nextLine(); // 사용자에게서 서버로 보낼 값을 입력받는 변수
out.println(inputLine); // 입력받은 키보드 값을 서버로 전송
}
} catch (Exception e) {
e.printStackTrace();
}
}
class SocketThread extends Thread { // 메시지 수신
public void run() {
try {
br = new BufferedReader(new InputStreamReader(cSocket.getInputStream())); // 송신 버퍼 객체 생성
String response = null; // 송신된 메시지를 저장하기 위한 변수
while ((response = br.readLine()) != null) { // br에 읽을 메시지가 있는 한 무한반복
System.out.println(response); // br 객체에 저장된 문자열을 한 줄 씩 받아와서 출력
}
} catch (Exception e) {
}
}
}
public static void main(String[] args) {
new TCPClient(); // 메인문에서 생성자 실행시켜주기
}
}
실행화면
반응형
'프로그래밍 > Java' 카테고리의 다른 글
[자바]소켓 서버-클라이언트 통신 실습 (0) | 2021.08.19 |
---|---|
뉴렉처 자바 JDBC 프로그래밍 강의 내용 정리 19-24강 (0) | 2021.08.17 |
뉴렉처 자바 JDBC 프로그래밍 강의 내용 정리 9-18강 (0) | 2021.08.16 |
뉴렉처 자바 JDBC 프로그래밍 강의 내용 정리 1-8강 (0) | 2021.08.16 |
[자바] 배열 역순 출력 (0) | 2020.11.09 |
[자바] 은행 프로그램(잔액 조회, 인출)(while문 활용) (0) | 2020.11.09 |