├── Client.java ├── README.md ├── Server.java ├── Socket ├── .gitignore ├── .idea │ ├── caches │ │ └── build_file_checksums.ser │ ├── codeStyles │ │ └── Project.xml │ ├── gradle.xml │ ├── misc.xml │ └── runConfigurations.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── jinwoo │ │ │ └── socket │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── jinwoo │ │ │ │ └── socket │ │ │ │ ├── MainActivity.kt │ │ │ │ └── SocketApplication.kt │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── jinwoo │ │ └── socket │ │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── Socket2 ├── .gitignore ├── .idea │ ├── caches │ │ └── build_file_checksums.ser │ ├── codeStyles │ │ └── Project.xml │ ├── gradle.xml │ ├── misc.xml │ └── runConfigurations.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── jinwoo │ │ │ └── socket2 │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── jinwoo │ │ │ │ └── socket2 │ │ │ │ ├── MainActivity.kt │ │ │ │ └── SocketApplication.kt │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── jinwoo │ │ └── socket2 │ │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle └── app.js /Client.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.io.InputStream; 3 | import java.io.OutputStream; 4 | import java.net.InetSocketAddress; 5 | import java.net.Socket; 6 | import java.net.UnknownHostException; 7 | 8 | public class Client { 9 | private static Socket socket; 10 | private static InputStream is; 11 | private static OutputStream os; 12 | 13 | public static void main(String[] args) { 14 | try { 15 | 16 | // socket = new Socket("localhost", 5001); 17 | 18 | socket = new Socket(); 19 | System.out.println("Server Connecting.."); 20 | socket.connect(new InetSocketAddress("localhost", 2000)); 21 | System.out.println("Server Connection OK!"); 22 | 23 | is = socket.getInputStream(); 24 | os = socket.getOutputStream(); 25 | 26 | byte[] byteArr = null; 27 | String msg = "Hello Server"; 28 | 29 | byteArr = msg.getBytes("UTF-8"); 30 | os.write(byteArr); 31 | os.flush(); 32 | System.out.println("Data Transmitted OK!"); 33 | 34 | byteArr = new byte[512]; 35 | int readByteCount = is.read(); 36 | 37 | if(readByteCount == -1) 38 | throw new IOException(); 39 | 40 | msg = new String(byteArr, 0, readByteCount, "UTF-8"); 41 | System.out.println("Data Received OK!"); 42 | System.out.println("Message : " + msg); 43 | 44 | is.close(); 45 | os.close(); 46 | 47 | } catch (UnknownHostException e) { 48 | // TODO Auto-generated catch block 49 | // IP Address가 잘못되었을 경우 50 | e.printStackTrace(); 51 | } catch (IOException e) { 52 | // TODO Auto-generated catch block 53 | // 해당 Port의 Server로 연결할 수 없는 경우 54 | e.printStackTrace(); 55 | try { socket.close(); } catch (IOException e1) { e1.printStackTrace(); } 56 | } 57 | 58 | if(!socket.isClosed()) { 59 | try { 60 | socket.close(); 61 | } catch (IOException e) { 62 | // TODO Auto-generated catch block 63 | e.printStackTrace(); 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Socket 2 | 3 | > TCP/IP Socket과 Socket io 사용법 4 | 5 | > 작성자 : 송진우 6 | 7 | > Present Time : 2018-09-28 8 | 9 | ## 0. 참고 자료 10 | * https://m.blog.naver.com/goldenkingll/70106915167 11 | * https://d2.naver.com/helloworld/1336 12 | * http://woowabros.github.io/woowabros/2017/09/12/realtime-service.html 13 | * https://github.com/socketio/socket.io-client-java 14 | 15 | ## 1. Socket 이란 16 | 17 | 두 프로그램이 네트워크를 통해 서로 통신을 수행 할 수 있도록 양쪽에 생성되는 링크의 단자입니다. 18 | 19 | - 데이터를 캡슐화하여 전달 가능 20 | - UNIX에서의 입출력 메소드의 표준인 개방/읽기/쓰기/닫기 메커니즘 21 | 22 | ![Socket 이미지](http://2.bp.blogspot.com/-ztRG8ei0eq4/TfBlm38bldI/AAAAAAAAAKw/sFf8d03WzYs/s1600/scheme.jpg) 23 | 24 | ## 2. TCP/IP Socket 25 | TCP 는 두 프로그램 간의 통신이 처음 시작될 때부터 끝날 때까지 계속 연결을 유지하는 연결지향(Connection oriented) 방식입니다. 26 | 27 | - 스트림 소켓 방식 28 | - 양쪽 어플리케이션 모두 데이터 주고 받기 가능 29 | - 흐름제어등을 보장해 주며 송신된 순서에 따른 중복되지 않은 데이터를 수신 가능 30 | - IP와 포트 번호로 소켓을 연결하면 통신 시작 31 | - byte 자료형으로 데이터를 보냄 32 | 33 | 34 | ### 2.1 통신 절차 35 | 36 | ![통신 절차](http://www.a2big.com/_images/product/web/main/jay/2012-07-2616:21:00.JPG) 37 | 38 | * TCP Client 39 | 1) 소켓을 생성합니다. 40 | 2) 서버로 connect() 합니다. 41 | 3) 접속이 성공됐다면 read 및 write 함수를 통해 서버와 통신을 주고 받습니다. 42 | 4) 사용을 마치면 close로 소켓을 닫습니다. 43 | 44 | * TCP Server 45 | 1) 듣기 소켓을 생선합니다. 46 | 2) bind합니다. (내선 부여) 47 | 3) listen합니다. (내선 연결) 48 | 4) accept() 클라이언트가 connect할 경우 소켓을 생성 하고 연결합니다. 49 | 5) read와 write 함수를 이용해 메시지를 주고 받습니다. 50 | 6) 사용된 연결 소켓을 닫습니다. 51 | 7) 사용을 마쳤을 경우 듣기 소켓을 닫습니다. 52 | 53 | ### 2.2 클라이언트 통신 과정 - JAVA 54 | #### 1. 소켓을 생성합니다. 55 | * Socket 객체를 생성 56 | ~~~java 57 | private static Socket socket; 58 | socket = new Socket(); 59 | ~~~ 60 | #### 2. 서버로 connect() 합니다. 61 | * 서버의 아이피와 포트번호를 적고 connect()로 연결합니다. 62 | ~~~java 63 | socket.connect(new InetSocketAddress("localhost", '포트번호')); 64 | ~~~ 65 | #### 3. 접속이 성공했다면 read 및 write 함수를 통해 서버와 통신을 주고 받습니다. 66 | * 스트림 소켓으로 통신하기 때문에 InputStream과 OutputStream을 만듭니다. 67 | * 또한 바이트 배열로 서버와 통신을 주고 받습니다. 68 | * OutputStream에 write() 로 데이터를 적습니다. 69 | * InputStream에 read() 로 서버의 데이터를 읽습니다. 70 | * 데이터 송수신시 데이터를 Charset으로 UTF 등을 설정할 수 있습니다. 71 | ~~~java 72 | private static InputStream is; 73 | private static OutputStream os; 74 | 75 | is = socket.getInputStream(); 76 | os = socket.getOutputStream(); 77 | 78 | byte[] byteArr = null; 79 | String msg = "Hello Server"; 80 | 81 | byteArr = msg.getBytes("UTF-8"); 82 | os.write(byteArr); 83 | os.flush(); 84 | System.out.println("Data Transmitted OK!"); 85 | 86 | byteArr = new byte[512]; 87 | int readByteCount = is.read(); 88 | 89 | if(readByteCount == -1) 90 | throw new IOException(); 91 | 92 | msg = new String(byteArr, 0, readByteCount, "UTF-8"); 93 | System.out.println("Data Received OK!"); 94 | System.out.println("Message : " + msg); 95 | 96 | ~~~ 97 | #### 4. 사용을 마치면 close로 소켓을 닫습니다. 98 | * 통신이 끊나면 스트림 소켓과 소켓을 close() 함수로 닫습니다. 99 | ~~~java 100 | is.close(); 101 | os.close(); 102 | 103 | socket.close(); 104 | ~~~ 105 | 106 | 107 | 108 | ### 2.3 (참고용) 서버 통신 과정 - JAVA 109 | 110 | #### 1. 듣기 소켓을 생성합니다. 111 | ~~~java 112 | private static ServerSocket serverSocket; 113 | serverSocket = new ServerSocket(); 114 | ~~~ 115 | #### 2. bind합니다. (내선 부여) 116 | ~~~java 117 | serverSocket.bind(new InetSocketAddress(3880)); 118 | ~~~ 119 | #### 3. listen합니다. (내선 연결) 120 | 클라이언트에서 요청이 올 때까지 기다린다!!!! 121 | #### 4. accept() 클라이언트가 connect할 경우 소켓을 생성 하고 연결합니다. 122 | ~~~java 123 | private static Socket socket; 124 | 125 | socket = serverSocket.accept(); 126 | ~~~ 127 | 128 | #### 5. read와 write 함수를 이용해 메시지를 주고 받습니다. 129 | ~~~java 130 | InputStream is = socket.getInputStream(); 131 | OutputStream os = socket.getOutputStream(); 132 | 133 | byte[] byteArr = new byte[512]; 134 | String msg = null; 135 | 136 | int readByteCount = is.read(byteArr); 137 | 138 | if(readByteCount == -1) 139 | throw new IOException(); 140 | 141 | msg = new String(byteArr, 0, readByteCount, "UTF-8"); 142 | System.out.println("Data Received OK!"); 143 | System.out.println("Message : " + msg); 144 | 145 | msg = "Hello Client"; 146 | byteArr = msg.getBytes("UTF-8"); 147 | os.write(byteArr); 148 | System.out.println("Data Transmitted OK!"); 149 | os.flush(); 150 | ~~~ 151 | 152 | #### 6. 사용된 연결 소켓을 닫습니다. 153 | ~~~java 154 | is.close(); 155 | os.close(); 156 | socket.close(); 157 | ~~~ 158 | 159 | #### 7. 사용을 마쳤을 경우 듣기 소켓을 닫습니다. 160 | ~~~java 161 | if(!serverSocket.isClosed()) { 162 | try { 163 | serverSocket.close(); 164 | } catch (IOException e) { 165 | // TODO Auto-generated catch block 166 | e.printStackTrace(); 167 | } 168 | } 169 | ~~~ 170 | 171 | ## 3. Socket.io 172 | 173 | - 실시간 이벤트 서버를 개발 할 수 있는 오픈소스 라이브러리 입니다. 174 | - WebSocket을 기반으로 FlashSocket, AJAX Long Polling등 다양한 방식의 실시간 웹 기술들을 하나의 API로 추상화한 node.js 모듈(MIT 라이센스 오픈소스) 175 | - 멀티 디바이스(web, android, ios, windows)를 지원합니다. 176 | 177 | ![Socket.io](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile26.uf.tistory.com%2Fimage%2F2406273E596D913E130B7B) 178 | 179 | ### 3.1 Socket.io 의 특징 180 | 181 | #### 장점 182 | 183 | - 통신 구현시 코드가 매우 감소합니다. 184 | - Socket의 성격과 같이 실시간 통신 가능 185 | - http를 통해 통신이 가능하고 JsonObject나 일반 Object로 통신이 가능합니다. 186 | - 브라우저와 웹 서버의 종류와 버전을 파악하여 가장 적합한 기술을 선택하여 사용하는 방식이기 때문에 브라우저의 종류와 상관없이 실시간 웹 구현 가능 187 | 188 | #### 단점 189 | 190 | - Socket.io는 Javascript에 초점이 만들어졌습니다. 191 | - 다양한 언어의 서버와 통신을 하기에는 제약이 있습니다. 192 | 193 | ### 3.2 Socket.io 클라이언트 - JAVA 194 | 195 | #### 1. 라이브러리 추가 196 | * Gradle에 socket.io를 추가합니다. 197 | ~~~java 198 | dependencies { 199 | ...생략 200 | implementation ('com.github.nkzawa:socket.io-client:1.0.0'){ 201 | exclude group: 'org.json', module: 'json' 202 | } 203 | } 204 | ~~~ 205 | 206 | #### 2. 소켓을 선언하고 초기화 207 | * TCP/IP와 동일하게 소켓을 만듭니다. 208 | * http로 연결이 가능하며, 서버의 주소와 포트 번호를 초기화 해줍니다. 209 | * URI 초기화 과정은 예외처리를 해주어야 합니다. 210 | ~~~java 211 | private Socket socket; 212 | { 213 | try{ 214 | socket = IO.socket("http://***.***.***.***:***"); 215 | } catch (URISyntaxException ue) { 216 | ue.printStackTrace(); 217 | } 218 | } 219 | ~~~ 220 | 221 | #### 3. 소켓을 연결 222 | * connect() 함수로 소켓을 연결합니다. 223 | ~~~java 224 | socket.connect(); 225 | ~~~ 226 | 227 | #### 4(1). 서버 측에 이벤트 송신 228 | * 클라이언트는 어떤 이벤트가 발생하면 이벤트를 서버로 송신할 수 있습니다. 229 | * emit() 함수를 통해 데이터 또는 메시지를 서버에 전달합니다. 230 | * 서버는 이를 이벤트의 이름으로 구분하여 수신합니다. 231 | ~~~java 232 | socket.emit("EVENT_NANE", DATA); 233 | ~~~ 234 | 235 | #### 4(2). 서버 측의 이벤트 수신 236 | * 서버는 다른 외부 클라이언트의 요청이나 서버의 이벤트 발생 시 클라이언트에 이벤트를 송신할 수 있습니다. 237 | * on() 함수를 통해 해당 이벤트 명을 이용해 구분하고 서버의 emit의 반응하는 리스너를 구현합니다. 238 | * 리스너 안의 call 함수 안에는 이벤트 수신 후 실행할 내용을 담습니다. 239 | ~~~java 240 | socket.on("EVENT_NAME", '리스너 익명구현 객체'); 241 | Emitter.Listener '리스너 익명구현 객체' = new Emitter.Listener() { 242 | @Override 243 | public void call(Object... args) { 244 | runOnUiThread(new Runnable() { 245 | @Override 246 | public void run() { 247 | // 이벤트 수신 시 실행할 내용들 248 | } 249 | }); 250 | ~~~ 251 | 252 | #### 5. 사용 후 연결 헤제 253 | * 서버와의 통신이 더 이상 필요 없는 경우 disconnect() 함수를 이용해 connect를 끊습니다. 254 | * 그리고 on 시켜 두었던 소켓도 off() 함수로 닫습니다. 255 | ~~~java 256 | protected void onDestroy() { 257 | super.onDestroy(); 258 | socket.disconnect(); 259 | socket.off("EVENT_NAME", '리스너 익명구현 객체'); 260 | } 261 | ~~~ 262 | 263 | ### 3.2 (참고용) Socket.io 서버 - Node.js 264 | ~~~javascript 265 | var app = require('express')(); 266 | var server = require('http').createServer(app); 267 | 268 | var io = require('socket.io')(server); 269 | 270 | io.on('connection', function(socket) { 271 | console.log("user connect"); 272 | 273 | socket.on('받은 이벤트 명', function(){ 274 | console.log("받은 이벤트 명"); 275 | io.emit('보낼 이벤트 명', "메시지나 데이터"); 276 | }); 277 | 278 | }); 279 | 280 | http.listen('포트 번호!', function(){ 281 | console.log("server on 포트번호"); 282 | }); 283 | ~~~ 284 | 285 | ## 4. 소켓 통신시 주의할 점 286 | * TCP/IP의 경우 데이터 타입을 byte배열로 해야하고 Charset을 해야 데이터가 꺠지지 않습니다. 287 | * 소켓을 생성하고 연결하여 사용을 하고 나면 꼭 정상적으로 소켓의 연결을 끊고 소켓을 닫아줘야 합니다. 288 | * 소켓도 통신이기 때문에 멀티 스레드를 활용하여 작업을 해줘야 성능 개선 및 로직이 엉키는 것을 방지할 수 있습니다. 289 | * Socket.io를 사용한다면 이벤트 명이 헷갈리지 않도록 잘 설정해야 합니다. 이벤트가 엇갈릴 경우 일일이 확인해야하는 불상사가 발생합니다. 290 | 291 | ## 5. Kotlin에 적용해보기 292 | ### 5.1 Java와 다른 점 293 | * static이 아니라 Kotlin에서는 companion object로 socket을 만들어줍니다. 294 | ~~~kotlin 295 | companion object { 296 | private lateinit var socket : Socket 297 | fun get(): Socket { 298 | try { 299 | socket = IO.socket("http://127.0.0.0:3000") 300 | } catch (e: URISyntaxException) { 301 | e.printStackTrace() 302 | } 303 | return socket 304 | } 305 | } 306 | ~~~ 307 | * 그 외 람다표현식을 좀 더 간편하게 사용할 수 있다는 점 외에는 다른 점이 없습니다. 308 | 309 | ### 5.2 emit을 보내는 어플리케이션 310 | ~~~kotlin 311 | class MainActivity : AppCompatActivity() { 312 | 313 | lateinit var Text : TextView 314 | lateinit var lighton_btn: Button 315 | lateinit var lightoff_btn: Button 316 | lateinit var socket: Socket 317 | 318 | override fun onCreate(savedInstanceState: Bundle?) { 319 | super.onCreate(savedInstanceState) 320 | setContentView(R.layout.activity_main) 321 | 322 | lighton_btn = findViewById(R.id.lighton_button) 323 | lightoff_btn = findViewById(R.id.lightoff_button) 324 | Text = findViewById(R.id.message) 325 | 326 | socket = SocketApplication.get() 327 | 328 | Text.setText("소켓 생성") 329 | 330 | socket.connect() 331 | 332 | lighton_btn.setOnClickListener { v -> 333 | socket.emit("lightOn") 334 | Text.setText("Light on Emit 성공") 335 | } 336 | 337 | lightoff_btn.setOnClickListener { v -> 338 | socket.emit("lightOff") 339 | Text.setText("Light off Emit 성공") 340 | } 341 | } 342 | } 343 | ~~~ 344 | 345 | ### 5.3 on을 받는 어플리케이션 346 | ~~~kotlin 347 | class MainActivity : AppCompatActivity() { 348 | 349 | lateinit var Text : TextView 350 | lateinit var Receive_Text: TextView 351 | lateinit var socket: Socket 352 | 353 | override fun onCreate(savedInstanceState: Bundle?) { 354 | super.onCreate(savedInstanceState) 355 | setContentView(R.layout.activity_main) 356 | 357 | Text = findViewById(R.id.message) 358 | Receive_Text = findViewById(R.id.receive_Text) 359 | 360 | socket = SocketApplication.get() 361 | 362 | socket.on("lightOn",light_on) 363 | socket.on("lightOff", light_off) 364 | socket.connect() 365 | } 366 | 367 | var light_on = Emitter.Listener { args -> 368 | Text.setText("소켓 on 성공") 369 | Receive_Text.setText(args[0].toString()) 370 | } 371 | 372 | var light_off = Emitter.Listener { args -> 373 | Text.setText("소켓 on 성공") 374 | Receive_Text.setText(args[0].toString()) 375 | } 376 | } 377 | ~~~ 378 | -------------------------------------------------------------------------------- /Server.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.io.InputStream; 3 | import java.io.OutputStream; 4 | import java.net.InetAddress; 5 | import java.net.InetSocketAddress; 6 | import java.net.ServerSocket; 7 | import java.net.Socket; 8 | import java.net.UnknownHostException; 9 | 10 | /** TCP/IP Server Socket 11 | * Network Programming 12 | * 13 | * @author Kitkat 14 | * 15 | */ 16 | public class Server { 17 | private static final String Naver = "www.naver.com"; 18 | private static ServerSocket serverSocket; 19 | private static Socket socket; 20 | 21 | public static void main(String[] args) { 22 | ipAddress(); 23 | 24 | try { 25 | 26 | // Instantiate ServerSocket Class 27 | serverSocket = new ServerSocket(); 28 | serverSocket.bind(new InetSocketAddress(2800)); 29 | 30 | 31 | // Connection Wait for Multiple Client 32 | while(true) { 33 | System.out.println("Connetion wait.."); 34 | socket = serverSocket.accept(); 35 | InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress(); 36 | System.out.println("Connection Accepted! Client [" + isa.getHostName() + ":" + isa.getPort() + "]"); 37 | 38 | InputStream is = socket.getInputStream(); 39 | OutputStream os = socket.getOutputStream(); 40 | 41 | byte[] byteArr = new byte[512]; 42 | String msg = null; 43 | 44 | int readByteCount = is.read(byteArr); 45 | 46 | if(readByteCount == -1) 47 | throw new IOException(); 48 | 49 | msg = new String(byteArr, 0, readByteCount, "UTF-8"); 50 | System.out.println("Data Received OK!"); 51 | System.out.println("Message : " + msg); 52 | 53 | msg = "Hello Client"; 54 | byteArr = msg.getBytes("UTF-8"); 55 | os.write(byteArr); 56 | System.out.println("Data Transmitted OK!"); 57 | os.flush(); 58 | 59 | is.close(); 60 | os.close(); 61 | socket.close(); 62 | } 63 | 64 | } catch (IOException e) { 65 | // TODO Auto-generated catch block 66 | e.printStackTrace(); 67 | try { socket.close(); } catch (IOException e1) { e1.printStackTrace(); } 68 | } 69 | 70 | if(!serverSocket.isClosed()) { 71 | try { 72 | serverSocket.close(); 73 | } catch (IOException e) { 74 | // TODO Auto-generated catch block 75 | e.printStackTrace(); 76 | } 77 | } 78 | } 79 | 80 | public static void ipAddress() { 81 | try { 82 | 83 | InetAddress inetAddress = InetAddress.getLocalHost(); 84 | System.out.println("LocalHost IP Address : " + inetAddress.getHostAddress()); 85 | 86 | InetAddress[] iaArr = InetAddress.getAllByName(Naver); 87 | 88 | for(InetAddress ia : iaArr) 89 | System.out.println(Naver + " IP Address : " + ia.getHostAddress()); 90 | 91 | } catch (UnknownHostException e) { 92 | // TODO Auto-generated catch block 93 | e.printStackTrace(); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /Socket/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | -------------------------------------------------------------------------------- /Socket/.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jinusong/Android-Socket/49d0ec28f4f1d754eb62d28fc99bba0095378528/Socket/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /Socket/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Socket/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /Socket/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /Socket/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /Socket/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Socket/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion 28 9 | defaultConfig { 10 | applicationId "com.jinwoo.socket" 11 | minSdkVersion 24 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 28 | implementation 'com.android.support:appcompat-v7:28.0.0-rc02' 29 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 30 | implementation ('io.socket:socket.io-client:1.0.0') { 31 | exclude group: 'org.json', module: 'json' 32 | } 33 | testImplementation 'junit:junit:4.12' 34 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 35 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 36 | } 37 | -------------------------------------------------------------------------------- /Socket/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /Socket/app/src/androidTest/java/com/jinwoo/socket/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.jinwoo.socket 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.jinwoo.socket", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Socket/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Socket/app/src/main/java/com/jinwoo/socket/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.jinwoo.socket 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import android.os.Bundle 5 | import android.widget.Button 6 | import android.widget.TextView 7 | import io.socket.client.Socket 8 | import io.socket.emitter.Emitter 9 | import org.json.JSONException 10 | 11 | class MainActivity : AppCompatActivity() { 12 | 13 | lateinit var Text : TextView 14 | lateinit var lighton_btn: Button 15 | lateinit var lightoff_btn: Button 16 | lateinit var socket: Socket 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | setContentView(R.layout.activity_main) 21 | 22 | lighton_btn = findViewById(R.id.lighton_button) 23 | lightoff_btn = findViewById(R.id.lightoff_button) 24 | Text = findViewById(R.id.message) 25 | 26 | socket = SocketApplication.get() 27 | 28 | socket.connect() 29 | 30 | Text.setText("소켓 생성") 31 | 32 | 33 | 34 | lighton_btn.setOnClickListener { v -> 35 | socket.emit("lightOn") 36 | Text.setText("Light on Emit 성공") 37 | } 38 | 39 | lightoff_btn.setOnClickListener { v -> 40 | socket.emit("lightOff") 41 | Text.setText("Light off Emit 성공") 42 | } 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Socket/app/src/main/java/com/jinwoo/socket/SocketApplication.kt: -------------------------------------------------------------------------------- 1 | package com.jinwoo.socket 2 | 3 | import android.app.Application 4 | import io.socket.client.IO 5 | import io.socket.client.Socket 6 | import java.net.URISyntaxException 7 | 8 | class SocketApplication: Application() { 9 | 10 | companion object { 11 | private lateinit var socket : Socket 12 | fun get(): Socket { 13 | try { 14 | socket = IO.socket("http://192.168.137.172:7000") 15 | } catch (e: URISyntaxException) { 16 | e.printStackTrace(); 17 | } 18 | return socket 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Socket/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /Socket/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /Socket/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 14 |