ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [원격제어 서비스 준비 1-2편] WebSocket 코드
    회사 생활/모바일 원격제어 서비스 2023. 12. 8. 10:42

    WebSocket 설명 보기 : 링크 

    Github 전체 코드 보기 : 링크

     

    안드로이드에서 WebSocket은 대부분 Okhttp3 라이브러리를 사용하는 것으로 보인다. 

     

    그래서 Okhttp3 라이브러리를 사용하는 간단히 예제를 만들어 보았다. 

     

    AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET"/>

     

    build.gradle

    implementation("com.squareup.okhttp3:okhttp:4.2.1")

     

    WebSocketHelper 클래스

    더보기
    import android.util.Log
    import okhttp3.OkHttpClient
    import okhttp3.Request
    import okhttp3.Response
    import okhttp3.WebSocket
    import okhttp3.WebSocketListener
    import okio.ByteString
    import org.json.JSONObject
    import java.util.concurrent.TimeUnit
    
    class WebSocketHelper : WebSocketListener() {
    
        private lateinit var webSocket: WebSocket
        private lateinit var client: OkHttpClient
        private lateinit var request: Request
    
        fun initWebSocket() {
            client = OkHttpClient.Builder()
                .pingInterval(30, TimeUnit.SECONDS)
                .build()
            request = Request.Builder()
                .url(url)
                .build()
            webSocket = client.newWebSocket(request, this)
        }
    
    
        override fun onOpen(webSocket: WebSocket, response: Response) {
            Log.d("WebSocketHelper", "WebSocket Connected")
            webSocket.send(convertStrToJsonStr("{message:hello}"))
        }
    
        override fun onMessage(webSocket: WebSocket, text: String) {
            Log.d("WebSocketHelper", "Receiving Message - text : $text")
        }
    
        override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
            Log.d("WebSocketHelper", "Receiving Bytes : $bytes")
        }
    
        override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
            Log.d("WebSocketHelper", "Closing coded : $code, Closing Reason $reason")
            webSocket.close(1000, null)
            webSocket.cancel()
        }
    
        override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
            Log.d("WebSocketHelper", "error message : ${t.message}, and error Response : $response")
        }
    
        fun convertStrToJsonStr(str: String): String {
            val jsonObject = JSONObject(str)
            return jsonObject.toString()
        }
    
        fun sendMessageToServer(text: String) {
            webSocket.send(text)
        }
    
        fun closeWebSocket() {
            webSocket.close(1000, "time to close WebSocket")
            client.dispatcher.executorService.shutdown()
        }
    
        companion object {
            private const val url = "ws://192.168.200.17:3000"
        }
    }

     

    1. WebSocketListener

     

    WebSocketListener는 OkHttp 라이브러리에서 제공되는 클래스로, WebSocket 이벤트를 처리하기 위한 콜백을 정의하는 인터페이스. 

     

    WebSocket은 서버와 클라이언트 간의 양방향 통신을 제공하는 프로토콜이며, 연결이 수립되거나 데이터가 수신되는 등의 이벤트가 발생할 때 이를 처리하기 위해 WebSocketListener를 사용합니다.

     

    • onOpen: WebSocket 연결이 성공적으로 수립되었을 때 호출됩니다.
    • onMessage: 웹소켓으로 데이터가 수신되었을 때 호출됩니다.
    • onClosing: 웹소켓 연결이 닫히기 전에 호출됩니다.
    • onClosed: 웹소켓 연결이 닫힌 후에 호출됩니다.
    • onFailure: 웹소켓 연결 중에 오류가 발생했을 때 호출됩니다.

     

    2. OkHttpClient

     

    OkHttpClient는 OkHttp 라이브러리에서 제공하는 HTTP 클라이언트이다.

    • OkHttpClient.Builder()를 사용하여 새로운 OkHttpClient를 생성
    • pingInterval(30, TimeUnit.SECONDS)는 WebSocket 연결이 유지되는 동안 주기적으로 핑을 보내는 간격을 설정하는 부분입니다. 이 경우 30초 간격으로 핑을 보냅니다.

     

    3. Request

    • Request.Builder()를 사용하여 새로운 HTTP 요청을 생성합니다.
    • url(url) 사용해서 WebSocket 서버의 URL을 설정

    url 세팅 부분:

    • (1) 만약 안드로이드 에뮬레이터를 사용할 것이라면 "ws://10.0.2.2:3000" 
    • (2) 개인 스마트폰으로 진행한다면 (윈도우) 터미널에서 'ipconfig' 을 쳐서 개인의 ethernet ipv4을 찾기 예) "ws://192.168.200.17:3000"

     

    MainActivity 클래스

    더보기
    class MainActivity : AppCompatActivity() {
    
        private lateinit var webSocketHelper: WebSocketHelper
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val editText = findViewById<EditText>(R.id.editText)
            val button = findViewById<Button>(R.id.button)
    
            webSocketHelper = WebSocketHelper()
            webSocketHelper.initWebSocket()
    
            button.setOnClickListener {
                var editStr: String = if (editText.text.toString() == "") "null" else editText.text.toString()
                val str = webSocketHelper.convertStrToJsonStr("{message:$editStr}")
                webSocketHelper.sendMessageToServer(str)
            }
        }
    
        override fun onDestroy() {
            super.onDestroy()
            webSocketHelper.closeWebSocket()
        }
    }

     

    WebSocketHelper 클래스를 불러오서 WebSocket에 필요한 부분들을 초기화 시켜주고

    버튼 클릭시 EditText에 있는 내용이 "message: 내용" 형태로 서버에 전달된다.

     

    node.js 서버 - index.js

    더보기
    const http = require("http")
    const Socket = require("websocket").server
    const server = http.createServer(()=>{})
    
    server.listen(3000,()=>{
        
    })
    
    const webSocket = new Socket({httpServer:server})
    
    webSocket.on('request',(req)=>{
        const connection = req.accept()
       
        connection.on('message',(message)=>{
            const data = JSON.parse(message.utf8Data)
            console.log(data);
            connection.send(JSON.stringify(
                data
            ))
        })
    
    })

     

    안드로이드 스크린샷:

     

    node.js를 실행시켰을때 들어온 값

Designed by Tistory.