[Android] Socket ํ†ต์‹  ๐Ÿ“ฉ

Jayยท2021๋…„ 1์›” 28์ผ
2

Android

๋ชฉ๋ก ๋ณด๊ธฐ
14/39
post-thumbnail

Socket !?

๋‘ ํ”„๋กœ๊ทธ๋žจ์ด ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์„œ๋กœ ํ†ต์‹ ์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์–‘์ชฝ์— ์ƒ์„ฑ๋˜๋Š” ๋งํฌ์˜ ๋‹จ์ž.

  • ๋ฐ์ดํ„ฐ๋ฅผ ์บก์Šํ™”ํ•˜์—ฌ ์ „๋‹ฌ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • UNIX์—์„œ์˜ ์ž…์ถœ๋ ฅ ๋ฉ”์†Œ๋“œ์˜ ํ‘œ์ค€์ธ ๊ฐœ๋ฐœ/์ฝ๊ธฐ/์“ฐ๊ธฐ/๋‹ซ๊ธฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

TCP/IP Socket

TCP๋Š” ๋‘ ํ”„๋กœ๊ทธ๋žจ ๊ฐ„ ํ†ต์‹ ์ด ์ฒ˜์Œ ์‹œ์ž‘๋  ๋•Œ๋ถ€ํ„ฐ ๋๋‚ ๋•Œ๊นŒ์ง€ ๊ณ„์† ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๋Š” ์—ฐ๊ฒฐ์ง€ํ–ฅ(Connection oriented) ๋ฐฉ์‹์ด๋‹ค.

  • ์ŠคํŠธ๋ฆผ ์†Œ์ผ“ ๋ฐฉ์‹
  • ์–‘์ชฝ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ชจ๋‘ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ํ๋ฆ„ ์ œ์–ด ๋“ฑ์„ ๋ณด์žฅํ•ด์ฃผ๋ฉฐ ์†ก์‹ ๋œ ์ˆœ์„œ์— ๋”ฐ๋ฅธ ์ค‘๋ณต๋˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ ์ˆ˜์‹  ๊ฐ€๋Šฅํ•˜๋‹ค.
  • IP์™€ ํฌํŠธ ๋ฒˆํ˜ธ๋กœ ์†Œ์ผ“์„ ์—ฐ๊ฒฐํ•˜๋ฉด ํ†ต์‹ ์ด ์‹œ์ž‘๋œ๋‹ค.
  • byte ์ž๋ฃŒํ˜•์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ธ๋‹ค.

ํ†ต์‹  ์ ˆ์ฐจ

  • TCP Client
  1. Socket ์ƒ์„ฑ
  2. ์„œ๋ฒ„๋กœ connect() ํ•œ๋‹ค.
  3. ์ ‘์†์ด ์„ฑ๊ณต ๋˜์—ˆ๋‹ค๋ฉด read & writeํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์™€ ํ†ต์‹ ์„ ์ฃผ๊ณ  ๋ฐ›๋Š”๋‹ค.
  4. ์‚ฌ์šฉ์ด ๋๋‚˜๋ฉด close๋กœ ์†Œ์ผ“์„ ๋‹ซ๋Š”๋‹ค.
  • TCP Server
  1. ๋“ฃ๊ธฐ ์†Œ์ผ“์„ ์ƒ์„ฑํ•œ๋‹ค.
  2. bindํ•œ๋‹ค. (๋‚ด์„  ๋ถ€์—ฌ)
  3. listenํ•œ๋‹ค. (๋‚ด์„  ์—ฐ๊ฒฐ)
  4. accept() ํด๋ผ์ด์–ธํŠธ๊ฐ€ connect ํ•  ๊ฒฝ์šฐ ์†Œ์ผ“์„ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•œ๋‹ค.
  5. read, write ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š”๋‹ค.
  6. ์‚ฌ์šฉ๋œ ์—ฐ๊ฒฐ ์†Œ์ผ“์„ ๋‹ซ๋Š”๋‹ค.
  7. ์‚ฌ์šฉ์„ ๋งˆ์ณค์„ ๊ฒฝ์šฐ, ๋“ฃ๊ธฐ ์†Œ์ผ“์„ ๋‹ซ๋Š”๋‹ค.

ํด๋ผ์ด์–ธํŠธ ํ†ต์‹  ๊ณผ์ • - JAVA

  1. ์†Œ์ผ“์„ ์ƒ์„ฑํ•œ๋‹ค.
  • Socket ๊ฐ์ฒด ์ƒ์„ฑ
private static Socket socket;
socket = new Socket();
  1. ์„œ๋ฒ„๋กœ connect()ํ•œ๋‹ค.
  • ์„œ๋ฒ„ IP์™€ ํฌํŠธ๋ฒˆํ˜ธ๋ฅผ ์ ๊ณ  connect()๋กœ ์—ฐ๊ฒฐ์„ ํ•œ๋‹ค.
socket.connect(new InetSocketAddress("localhost","portNumber"));
  1. ์ ‘์†์ด ์„ฑ๊ณตํ–ˆ๋‹ค๋ฉด read & write ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์™€ ํ†ต์‹ ์„ ์ฃผ๊ณ  ๋ฐ›๋Š”๋‹ค.
  • stream socket์œผ๋กœ ํ†ต์‹ ํ•˜๊ธฐ์— InputStream, OutputStream์„ ๋งŒ๋“ ๋‹ค.
  • ๋˜ํ•œ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ์„œ๋ฒ„์™€ ํ†ต์‹ ์„ ์ฃผ๊ณ  ๋ฐ›๋Š”๋‹ค.
  • OutputStream์— write()๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ ๋Š”๋‹ค.
  • InputStream์— read()๋กœ ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š”๋‹ค.
  • ๋ฐ์ดํ„ฐ ์†ก์ˆ˜์‹ ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ Charset์œผ๋กœ UTF๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
private static InputStream is;
private static OutputStream os;

is = socket.getInputStream();
os = socket.getOutputStream();

byte[] byteArr = null;
String msg = "Hello Server";

byteArr = msg.getBytes("UTF-8");
os.write(byteArr);
os.flush();
System.out.println("Data Trasmitted OK!");

byteArr = new byte[512];
int readByteCount = is.read();

if(readByteCount == -1)
	throw new IOException();
    
msg = new String(byteArr, 0, readByteCount, "UTF-8");
System.out.println("Data Received OK!");
System.out.println("Message : "+ msg);
  1. ์‚ฌ์šฉ์„ ๋งˆ์น˜๋ฉด close๋กœ ์†Œ์ผ“์„ ๋‹ซ๋Š”๋‹ค.
  • ํ†ต์‹ ์ด ๋๋‚˜๋ฉด ์ŠคํŠธ๋ฆผ ์†Œ์ผ“๊ณผ ์†Œ์ผ“์„ close()ํ•จ์ˆ˜๋กœ ๋‹ซ๋Š”๋‹ค.
is.close();
os.close();

socket.close();

Socket.io

  • ์‹ค์‹œ๊ฐ„ ์ด๋ฒคํŠธ ์„œ๋ฒ„๋ฅผ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

ํŠน์ง•

์žฅ์ 

  • ํ†ต์‹  ๊ตฌํ˜„ ์‹œ ์ฝ”๋“œ๊ฐ€ ๋งค์šฐ ๊ฐ์†Œํ•œ๋‹ค.
  • Socket์˜ ์„ฑ๊ฒฉ๊ณผ ๊ฐ™์ด ์‹ค์‹œ๊ฐ„ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • http๋ฅผ ํ†ตํ•ด ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๊ณ  JsonObject๋‚˜ ์ผ๋ฐ˜ Object๋กœ ํ†ต์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €์™€ ์›น์„œ๋ฒ„์˜ ์ข…๋ฅ˜์™€ ๋ฒ„์ „์„ ํŒŒ์•…ํ•˜์—ฌ ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๊ธฐ์— ๋ธŒ๋ผ์šฐ์ € ์ข…๋ฅ˜ ์ƒ๊ด€์—†์ด ์‹ค์‹œ๊ฐ„ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋‹จ์ 

  • Socket.io๋Š” JavaScript์— ์ดˆ์ ์ด ๋งŒ๋“ค์–ด์กŒ๋‹ค.
  • ๋‹ค์–‘ํ•œ ์–ธ์–ด์˜ ์„œ๋ฒ„์™€ ํ†ต์‹ ์„ ํ•˜๊ธฐ์—๋Š” ์ œ์•ฝ์ด ์žˆ๋‹ค.

์‚ฌ์šฉํ•ด๋ณด๊ธฐ

1๏ธโƒฃ Gradle์— ์ถ”๊ฐ€ํ•˜๊ธฐ.

implementation ('com.github.nkzawa:socket.io-client:1.0.0')

2๏ธโƒฃ ์†Œ์ผ“ ์„ ์–ธ๊ณผ ์ดˆ๊ธฐํ™”

  • TCP/IP์™€ ๋™์ผํ•˜๊ฒŒ ์†Œ์ผ“์„ ๋งŒ๋“ ๋‹ค.
  • http๋กœ ์—ฐ๊ฒฐ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์„œ๋ฒ„์˜ ์ฃผ์†Œ์™€ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ดˆ๊ธฐํ™” ํ•ด์ค€๋‹ค.
  • URI ์ดˆ๊ธฐํ™” ๊ณผ์ •์€ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.
private Socket socket;
{
	try{
    	socket = IO.socket("http://***.****:****");       
    } catch (URISyntaxException ue) {
    	ue.printStackTrace();
    }
}

3๏ธโƒฃ ์†Œ์ผ“์„ ์—ฐ๊ฒฐ

  • connect() ํ•จ์ˆ˜๋กœ ์†Œ์ผ“์„ ์—ฐ๊ฒฐํ•œ๋‹ค.
socket.connect();

4๏ธโƒฃ Server์— ์ด๋ฒคํŠธ ์†ก์‹ 

  • Client๋Š” ์–ด๋–ค ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฒคํŠธ๋ฅผ ์„œ๋ฒ„๋กœ ์†ก์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • emit() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ๋˜๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ์„œ๋ฒ„์— ์ „๋‹ฌํ•œ๋‹ค.
  • ์„œ๋ฒ„๋Š” ์ด๋ฅผ ์ด๋ฒคํŠธ์˜ ์ด๋ฆ„์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ˆ˜์‹ ํ•œ๋‹ค.
socket.emit("EVENT_NAME", DATA);

5๏ธโƒฃ Server ์ธก ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ 

  • ์„œ๋ฒ„๋Š” ๋‹ค๋ฅธ ์™ธ๋ถ€ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด๋‚˜ ์„œ๋ฒ„์˜ ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ํด๋ผ์ด์–ธํŠธ์— ์ด๋ฒคํŠธ๋ฅผ ์†ก์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • on()ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์ด๋ฒคํŠธ ๋ช…์„ ์ด์šฉํ•ด ๊ตฌ๋ถ„ํ•˜๊ณ  ์„œ๋ฒ„์˜ emit์˜ ๋ฐ˜์‘ํ•˜๋Š” ๋ฆฌ์Šค๋„ˆ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.
  • ๋ฆฌ์Šค๋„ˆ ์•ˆ์˜ call ํ•จ์ˆ˜ ์•ˆ์—๋Š” ์ด๋ฒคํŠธ ์ˆ˜์‹  ํ›„ ์‹คํ–‰ํ•  ๋‚ด์šฉ์„ ๋‹ด๋Š”๋‹ค.
socket.on("EVENT_NAME", '๋ฆฌ์Šค๋„ˆ ์ต๋ช…๊ตฌํ˜„ ๊ฐ์ฒด');
Emitter.Listener '๋ฆฌ์Šค๋„ˆ ์ต๋ช…๊ตฌํ˜„ ๊ฐ์ฒด' = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // ์ด๋ฒคํŠธ ์ˆ˜์‹  ์‹œ ์‹คํ–‰ํ•  ๋‚ด์šฉ๋“ค
                }
            });

6๏ธโƒฃ ์‚ฌ์šฉ ํ›„ ์—ฐ๊ฒฐ ํ•ด์ œ

  • ์„œ๋ฒ„์™€์˜ ํ†ต์‹ ์ด ๋” ์ด์ƒ ํ•„์š” ์—†๋Š” ๊ฒฝ์šฐ disconnect()ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด connect๋ฅผ ๋Š๋Š”๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  on ์‹œ์ผœ ๋‘์—ˆ๋˜ ์†Œ์ผ“๋„ off() ํ•จ์ˆ˜๋กœ ๋‹ซ๋Š”๋‹ค.
protected void onDestroy() {
        super.onDestroy();
        socket.disconnect();
        socket.off("EVENT_NAME", '๋ฆฌ์Šค๋„ˆ ์ต๋ช…๊ตฌํ˜„ ๊ฐ์ฒด');
    }

์†Œ์ผ“ ํ†ต์‹  ์‹œ ์ฃผ์˜ํ•  ์ 

  • TCP/IP์˜ ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ byte๋ฐฐ์—ด๋กœ ํ•ด์•ผํ•˜๊ณ  Charset์„ ํ•ด์•ผ ๋ฐ์ดํ„ฐ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๋Š”๋‹ค.
  • ์†Œ์ผ“์„ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ  ๋‚˜๋ฉด ๋ฐ˜๋“œ์‹œ ์ •์ƒ์ ์œผ๋กœ ์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ๋Š๊ณ  ๋‹ซ์•„์ค˜์•ผํ•œ๋‹ค.
  • ์†Œ์ผ“๋„ ํ†ต์‹ ์ด๊ธฐ์— ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ๋ฅผ ํ™œ์šฉํ•ด์„œ ์ž‘์—…์„ ํ•ด์•ผ ์„ฑ๋Šฅ ๊ฐœ์„  ๋ฐ ๋กœ์ง์ด ์—‰ํ‚ค์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.
  • Socket.io๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋ฒคํŠธ ๋ช…์ด ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋„๋ก ์ž˜ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.
    ์ด๋ฒคํŠธ๊ฐ€ ์—‡๊ฐˆ๋ฆด ๊ฒฝ์šฐ, ํ•˜๋‚˜์”ฉ ํ™•์ธํ•ด์•ผํ•œ๋‹ค.

Socket with Kotlin

Java์™€์˜ ์ฐจ๋ณ„์ 

  • static์ด ์•„๋‹ˆ๋ผ kotlin์—์„œ๋Š” companion object๋กœ socket์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.
companion object {
    private lateinit var socket : Socket
    fun get(): Socket {
        try {
            socket = IO.socket("http://127.0.0.0:3000")
            } catch (e: URISyntaxException) {
                e.printStackTrace()
            }
                return socket
            }
        }
  • ๊ทธ ์ด์™ธ์— ๋žŒ๋‹คํ‘œํ˜„์‹์œผ๋กœ ์ข€ ๋” ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Example

emit application

class MainActivity : AppCompatActivity() {

    lateinit var Text : TextView
    lateinit var lighton_btn: Button
    lateinit var lightoff_btn: Button
    lateinit var socket: Socket

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        lighton_btn = findViewById(R.id.lighton_button)
        lightoff_btn = findViewById(R.id.lightoff_button)
        Text = findViewById(R.id.message)

        socket = SocketApplication.get()

        Text.setText("์†Œ์ผ“ ์ƒ์„ฑ")

        socket.connect()

        lighton_btn.setOnClickListener { v ->
            socket.emit("lightOn")
            Text.setText("Light on Emit ์„ฑ๊ณต")
        }

        lightoff_btn.setOnClickListener { v ->
            socket.emit("lightOff")
            Text.setText("Light off Emit ์„ฑ๊ณต")
        }
    }
}

on application

class MainActivity : AppCompatActivity() {

    lateinit var Text : TextView
    lateinit var Receive_Text: TextView
    lateinit var socket: Socket

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Text = findViewById(R.id.message)
        Receive_Text = findViewById(R.id.receive_Text)

        socket = SocketApplication.get()

        socket.on("lightOn",light_on)
        socket.on("lightOff", light_off)
        socket.connect()
    }

    var light_on = Emitter.Listener { args ->
        Text.setText("์†Œ์ผ“ on ์„ฑ๊ณต")
        Receive_Text.setText(args[0].toString())
    }

    var light_off = Emitter.Listener { args ->
        Text.setText("์†Œ์ผ“ on ์„ฑ๊ณต")
        Receive_Text.setText(args[0].toString())
    }
}
profile
developer

0๊ฐœ์˜ ๋Œ“๊ธ€