package chat;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
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.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerExample extends Application {
ExecutorService executorService;
ServerSocket serverSocket;
List connections = new Vector(); // ì¤ë ëì ìì í¨
void startServer(){
// ìë² ìì ì½ë (Executor Service ìì±, ServerSocket ìì± ë° í¬í¸ ë°ì¸ë©, ì°ê²° ìë½)
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
try{
serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("localhost", 5001));
}catch(Exception e){
if(!serverSocket.isClosed()) { stopServer();}
return;
}
Runnable runnable = new Runnable() { // ìë½ ìì
ì ìì±
@Override
public void run() {
Platform.runLater(()-> {
// UI ì¤ì
displayText("[ìë² ìì]");
btnStartStop.setText("stop");
});
while(true){
try{
Socket socket = serverSocket.accept(); // ì°ê²° ìë½
String message = "[ì°ê²° ìë½ : " + socket.getRemoteSocketAddress() + ": " + Thread.currentThread().getName() + "]";
Platform.runLater(()->displayText(message));
Client client = new Client(socket);
connections.add(client);
Platform.runLater(()-> displayText("[ì°ê²° ê°ì : " + connections.size() + " ]"));
}catch(Exception e){
if(!serverSocket.isClosed()) { stopServer();}
break;
}
}
}
};
executorService.submit(runnable); // ì¤ë ë íìì ì²ë¦¬
}
void stopServer(){
// ìë² ì¢
ë£ ì½ë
try{
Iterator iterator = connections.iterator();
while(iterator.hasNext()){ // 모ë socket ë«ê¸°
Client client = iterator.next();
client.socket.close();
iterator.remove();
}
if(serverSocket != null && !serverSocket.isClosed()){ // server socket ë«ê¸°
serverSocket.close();
}
if(executorService != null && !executorService.isShutdown()){ // ExecutorService ì¢
ë£
executorService.shutdown();
}
Platform.runLater(() -> {
displayText("[ìë² ë©ì¶¤]");
btnStartStop.setText("start");
});
}catch(Exception e){ }
}
class Client {
// ë°ì´í° íµì ì½ë
Socket socket;
Client(Socket socket){
this.socket = socket;
receive();
}
void receive(){
// ë°ì´í° ë°ê¸° ì½ë
Runnable runnable = new Runnable() { // ë°ê¸° ìì
ìì±
@Override
public void run() {
try{
while(true){
byte[] byteArr = new byte[100];
InputStream inputStream = socket.getInputStream();
int readByteCount = inputStream.read(byteArr); // ë°ì´í° ë°ê¸°
// í´ë¼ì´ì¸í¸ê° ì ìì ì¼ë¡ Socketì close()를 í¸ì¶íì ê²½ì°
if(readByteCount == -1) { throw new IOException();}
String message = "[ìì² ì²ë¦¬: " + socket.getRemoteSocketAddress() + ": " + Thread.currentThread().getName() + "]";
Platform.runLater(()->displayText(message));
String data = new String(byteArr, 0, readByteCount, "UTF-8");
for(Client client : connections){
client.send(data); // 모ë í´ë¼ì´ì¸í¸ìê² ë³´ë
}
}
}catch(Exception e){
try{
connections.remove(Client.this);
String message = "[í´ë¼ì´ì¸í¸ íµì ìë¨: " + socket.getRemoteSocketAddress() + ": " + Thread.currentThread().getName() + " ]";
Platform.runLater(()->displayText(message));
socket.close();
}catch(IOException e2) {}
}
}
};
executorService.submit(runnable); // ì¤ë ëíìì ì²ë¦¬
}
void send(String data){
// ë°ì´í° ì ì¡ ì½ë
Runnable runnable = new Runnable() { // ë³´ë´ê¸° ìì
ìì±
@Override
public void run() {
try{
byte[] byteArr = data.getBytes("UTF-8");
OutputStream outputStream = socket.getOutputStream();
outputStream.write(byteArr);
outputStream.flush();
}catch(Exception e){
try {
String message = "[í´ë¼ì´ì¸í¸ íµì ìë¨: " + socket.getRemoteSocketAddress() + ": " + Thread.currentThread().getName() + " ]";
Platform.runLater(() -> displayText(message));
connections.remove(Client.this);
socket.close();
}catch(IOException e2) {}
}
}
};
executorService.submit(runnable); // ì¤ë ëíìì ì²ë¦¬
}
}
////////
// UI ìì± ì½ë
TextArea txtDisplay;
Button btnStartStop;
@Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
root.setPrefSize(500, 300);
txtDisplay = new TextArea();
txtDisplay.setEditable(false);
BorderPane.setMargin(txtDisplay, new Insets(0,0,2,0));
root.setCenter(txtDisplay);
btnStartStop = new Button("start");
btnStartStop.setPrefHeight(30);
btnStartStop.setMaxWidth(Double.MAX_VALUE);
btnStartStop.setOnAction(e->{
if(btnStartStop.getText().equals("start")){
startServer();
}else if(btnStartStop.getText().equals("stop")){
stopServer();
}
});
root.setBottom(btnStartStop);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("app.css").toString());
primaryStage.setScene(scene);
primaryStage.setTitle("Server");
primaryStage.setOnCloseRequest(event->stopServer());
primaryStage.show();
}
void displayText(String text){
txtDisplay.appendText(text + "\n");
}
public static void main(String[] args){
launch(args);
}
}