이번에 백엔드를 공부하면서 간단하게 소켓을 만들어 보게 되어서 포스팅합니다.
class IOClient {
// 소켓을 열기 위한 함수
fun openSocket() {
// 예외를 처리하기 위해 runCatching 사용
runCatching {
// 새로운 소켓을 생성하고 localhost:8080 서버에 연결
val socket = Socket()
socket.connect(InetSocketAddress("localhost", 8080))
// 서버로 데이터를 전송하기 위한 출력 스트림 설정
val outputStream = socket.getOutputStream()
val body = "클라이언트입니다" // 전송할 메시지
outputStream.write(body.toByteArray())
outputStream.flush()
// 서버로부터 데이터를 읽기 위한 입력 스트림 설정
val inputStream = socket.getInputStream()
val response = ByteArray(1024)
inputStream.read(response)
// 서버로부터 받은 응답을 출력
println("클라이언트: ${response.decodeToString()}")
}.onFailure {
// 예외가 발생한 경우 스택 트레이스 출력
it.printStackTrace()
}
}
}
서버에게 요청을 보낼 클라이언트를 만들어줍니다.
class IOServer {
// 서버를 열기 위한 함수
fun openServer() {
// 예외를 처리하기 위해 runCatching 사용
runCatching {
println("서버 열기")
// 새로운 서버 소켓 생성 및 localhost:8080에서 연결 대기
val server = ServerSocket()
server.bind(InetSocketAddress("localhost", 8080))
// 클라이언트의 연결을 계속해서 수락
while (true) {
val client = server.accept()
// 클라이언트로부터의 요청을 읽기 위한 입력 스트림 설정
val request = ByteArray(1024)
val inputStream = client.getInputStream()
inputStream.read(request)
println("서버:" +request.decodeToString())
// 클라이언트에게 응답을 보내기 위한 출력 스트림 설정
val outputStream = client.getOutputStream()
val response = "서버입니다" // 응답 메시지
outputStream.write(response.toByteArray())
outputStream.flush()
}
}.onFailure {
// 예외가 발생한 경우 스택 트레이스 출력
it.printStackTrace()
}
}
}
클라이언트 요청을 처리해줄 서버를 만들어 줍시다.
서버가 먼저 실행되어야 클라이언트의 요청을 처리해 줄 수 있겠죠?
fun main() {
CoroutineScope(Dispatchers.IO).launch {
launch {
delay(100)
IOClient().openSocket()
}
launch {
IOServer().openServer()
}
}
Thread.sleep(1000)
}
코루틴을 이용해서 동시에 실행하되 서버 먼저 실행되도록 했습니다.
서버에는 클라이언트의 request가
클라이언트에는 서버의 response가 잘 출력되는 것을 확인 할 수 있습니다.