Server
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.ServerSocket
import java.net.Socket
import kotlin.concurrent.thread
const val PORT = 1234
fun main() {
startServer()
}
fun startServer() {
// 서버 소켓 생성 및 클라이언트 수신 대기
val serverSocket: ServerSocket = ServerSocket(PORT)
println("Server socket established on port $PORT")
while(true) {
// 클라이언트 연결 요청 수락
val clientSocket: Socket = serverSocket.accept()
println("Client connected from " + clientSocket.getInetAddress().getHostAddress())
thread {
handleClient(clientSocket)
}
}
}
fun handleClient(clientSocket: Socket) {
try {
// 클라이언트 측 요청 수신을 위한 입력 스트림 설정
val input = BufferedReader(InputStreamReader(clientSocket.getInputStream()))
// 클라이언트 측 요청 전송을 위한 출력 스트림 설정
val output = PrintWriter(clientSocket.getOutputStream(), true)
// Server -> Client
output.println("Welcome to the kotlin Server!")
// Client -> Server
var message: String?
while (input.readLine().also { message = it } != null) {
println("Received from client: $message")
if (message.equals("exit", ignoreCase = true)) {
output.println("Goodbye!")
break
}
output.println("Server received: $message")
}
} catch (e: Exception) {
println("Error handling client: ${e.message}")
} finally {
clientSocket.close()
println("Client disconnected")
}
}
- Socket - InputStream & OutputStream
- InputStream : 소켓을 통해 상대방이 보낸 데이터를 읽어 들이는 통로 (수신)
- OutputStream : 소켓을 통해 상대방에게 데이터를 보내는 통로 (송신)
- input.readLine().also { message = it } != null
- input.readLine() : 클라이언트에서 전송된 메시지를 읽는다.
- .also { message = it } : 입력값을 it로 전달하고, 그걸 다시 message 할당한다.
- != null : message가 null이 아닌지 확인한다.
Client
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.Socket
const val SERVER_ADDRESS = "127.0.0.1"
const val PORT = 1234
fun main() {
startClient()
}
fun startClient() {
try {
// Socket 생성 및 서버 연결 시도
val socket = Socket(SERVER_ADDRESS, PORT)
println("Connected to server at $SERVER_ADDRESS:$PORT")
// 서버 측 데이터 전송을 위한 출력 스트림 설정
val output = PrintWriter(socket.getOutputStream(), true)
// 서버 측 데이터 수신을 위한 입력 스트림 설정
val input = BufferedReader(InputStreamReader(socket.getInputStream()))
val consoleInput = BufferedReader(InputStreamReader(System.`in`))
println("Server: ${input.readLine()}")
while (true) {
print ("Enter Message ('exit' to quit): ")
val userInput = consoleInput.readLine()
if (userInput.isNullOrEmpty()) continue
output.println(userInput)
if (userInput.equals("exit", ignoreCase = true)) {
break
}
val response = input.readLine()
if (response == null) {
println("Server disconnected unexpectedly.")
break
}
println("Server: $response")
}
} catch (e: Exception) {
println("Could not connect to server: ${e.message}")
}
}
참고 자료
'Backend' 카테고리의 다른 글
| [Backend] JVM의 의존성 관리와 빌드 도구 분석 (0) | 2025.10.17 |
|---|---|
| [Backend] ByteArray class 이해하기 (1) | 2025.10.16 |
| [Backend] Kotlin N:N Chat Application (Blocking Socket) (0) | 2025.10.14 |
| [Backend] Pub-Sub 패턴: 경쟁적 소비 모델 vs. Broadcast (0) | 2025.10.10 |
| [Backend] volatile 키워드, 언제 쓰고 왜 쓰는가? (2) | 2025.10.04 |