티스토리 뷰
안녕하세요. 오늘을 날개라는 프로젝트를 진행하면서 얻은 Socket통신에 대한 경험을 공유하고자 합니다.
현재 안드로이드와 라즈베리파이간의 통신을 Socket을 이용하고 있습니다.
관련 코드은 하단에서 확인하실 수 있습니다. (Star와 Issue는 언제나 환영!)
Kotlin과 RxJava로 이루어진 Socket Client 통신
Socket를 사용하는 이유
IoT와 안드로이드 어플간의 통신은 보통 블루투스로 구현합니다.
하지만 블루투스 통신의 페어링은 굉장히 귀찮은 과정입니다...
그래서 페어링 없는, 어플만 켜면 자동으로 연결되는 통신을 원했으며
같은 네트워크에 있다면 아무런 과정없이 연결할 수 있는 Socket을 사용하게 되었습니다.
Socket 통신 With Kotlin, Python
Socket은 클라이언트와 서버로 나뉩니다.
한명은 Server가 되어 Client를 기다리며 Client는 Server기기의 IP를 통하여 Server에 접속합니다.
Socket Client Kotlin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.* | |
val ip = '여기에 ip를 입력해주세요.' // 192.168.0.0 | |
val port = 3000 // 여기에 port를 입력해주세요 | |
val socket = Socket(ip, port) // ip와 port를 입력하여 클라이언트 소켓을 만듭니다. | |
val outStream = socket.outputStream // outputStream - 데이터를 내보내는 스트림입니다. | |
val inStream = socket.inputStream // inputStream - 데이터를 받는 스트림입니다. | |
val data = "여기에 데이터를 입력하세요." // 데이터는 byteArray로 변경 할 수 있어야 합니다. | |
outStream.write(data.toByteArray()) // toByteArray() 파라미터로 charset를 설정할 수 있습니다. 기본값 utf-8 | |
val available = inStream.available() // 데이터가 있으면 데이터의 사이즈 없다면 -1을 반환합니다. | |
if (available > 0){ | |
val dataArr = ByteArray(available) // 사이즈에 맞게 byte array를 만듭니다. | |
outStream.read(dataArr) // byte array에 데이터를 씁니다. | |
val data = String(dataArr) // byte array의 데이터를 통해 String을 만듭니다. | |
println("data : ${data}") | |
} | |
Socket Server Kotlin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.* | |
import java.net.* | |
val port = 3000 // port를 설정합니다. | |
val serverSocket = ServerSocket(port) | |
val client = serverSocket.accept() // 서버에 접근한 클라이언트와 통신할 수 있는 소켓을 만듭니다. | |
val clientInput = client.inputStream // 클라이언트와 연결된 inputstream | |
val clientOutput = client.outputStream // 클라이언트와 연결된 outputstream | |
// 이 후 동작은 위의 client.kt와 같습니다. | |
// 서버는 accept()를 통하여 클라이언트를 기다리며 | |
// 클라이언트가 연결되면 socket을 반환합니다. |
Socket Client Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from socket import socket | |
client_socket = socket() | |
# 기본적인 클라이언트 소켓을 만든다 | |
ip = 'localhost' | |
# 원하는 ip와 port를 설정하고 | |
port = 30000 | |
client_socket.connect((host, port)) | |
# 해당 소켓을 연결한다!! 코틀린과의 다른점 | |
data = '여기에 데이터를 입력하세요.' | |
# data를 encode한 후 send에 넣습니다. | |
client_socket.send(data.encode('utf-8')) | |
data = client_socket.recv(1024).decode('utf-8') | |
# 1024라는 사이즈를 설정하여 받은 데이터를 utf-8로 decode합니다. | |
print(data) |
Socket Server Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from socket import socket, AF_INET, SOCK_STREAM | |
server_socket = socket(AF_INET, SOCK_STREAM) | |
# 서버 소켓을 만듭니다. | |
ip = 'localhost' | |
# 원하는 ip와 port를 설정하고 | |
port = 3000 | |
server_socket.bind((ip, port)) | |
# 서버 소켓을 바인딩합니다. | |
server_socket.listen(100) | |
# 서버 소켓이 클라이언트를 받을 수 있습니다. | |
client_socket, addr = server_socket.accept() | |
# client와 ip를 받을 수 있습니다. | |
client_socket.send(data.encode('utf-8')) | |
client_socket.recv(1024).decode('utf-8') | |
# 이 후 동작은 위의 client.py와 같습니다. |
어떠신가요? 별로 어렵지 않죠? 위 코드들을 따라하면 쉽게 Socket 통신을 구현하실 수 있습니다.
Socket통신을 하면서 한 삽질 공유
- 안드로이드에서 Socket과 같은 네트워크 동작은 main 쓰레드에서 하면 안됩니다.
- Socket이 close되지 않고 예외로 인한 강제종료가 발생 할 때
다른 기기의 Socket은 끊겨있는지 모릅니다. available이나 isClosed로 확인 안됩니다.
(이거 때문에 애 많이 먹었습니다. 참고하세요!)
제 글로 인해 많은 사람들에게 도움이 되기를 바라며...
감사합니다!
'기술 및 라이브러리 소개' 카테고리의 다른 글
드래그로 item 옮기기 - RAReorderableLayout (0) | 2018.05.09 |
---|---|
안드로이드 Permisson 관리 - TedPermission (0) | 2018.05.07 |
RxJava - Observable이란? (0) | 2018.05.06 |
안드로이드 Bluetooth 통신 with Kotlin (0) | 2018.05.05 |
RxJava란? (0) | 2018.05.03 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday