멤버십 과제중 안드로이드로 게임통신을 해야하는 부분에서 자바에 WSASelect 가 없으므로 비동기 소켓을 보내고 받는것이 익숙치 않았다. IOCP 소켓이란 것이 이미 윈도우의 이벤트를 이용 하는 것이기 때문에, 자바에서는 100% 맞는 통신은 없지만, 아래와 같이 channel selector 를 이용하여 비슷한 효과로 비동기 소켓을 처리 할 수 있다.
자바는 WSAselect 가 없기 때문에 IOCP 통신을 해주기위해서 select 개념을 사용해야 한다.
MainActivity.java
import android.os.Bundle; import android.app.Activity; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
SimpleChatClient scc = new SimpleChatClient(); scc.initServer(); scc.startServer(); } } |
SimpleChatClient.java
package com.example.iocpclient; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.Iterator; import android.util.Log; public class SimpleChatClient { private static final String HOST = "210.118.64.148"; private static final int PORT = 5056; private Selector selector = null; private SocketChannel sc = null; private Charset charset = null; private CharsetDecoder decoder = null;
public SimpleChatClient(){//Handler MainAct) { charset = Charset.forName("EUC-KR"); decoder = charset.newDecoder(); } public void initServer() { try { // open Selector selector = Selector.open(); // 소켓채널을 생성한다. sc = SocketChannel.open(new InetSocketAddress(HOST, PORT)); // 비 블록킹 모드로 설정한다. sc.configureBlocking(false); // 서버소켓 채널을 셀렉터에 등록한다. sc.register(selector, SelectionKey.OP_READ);
} catch (IOException ex) {
Log.e("aaa", "_____________________1" + ex.toString()); System.exit(0);
// log(Level.WARNING, "SimpleChatClient.initServer()", ex); }
} public void startServer() { //startWriter(); Thread tWriter = new WriteThread(sc); tWriter.start();
/*쓰레드 추가 */ ReaderThread tReader = new ReaderThread(); tReader.start();
} public class ReaderThread extends Thread { public ReaderThread(){
} public void run() {
try {
while (true) {
// info("요청을 기다리는중...");
// 셀렉터의 select() 메소드로 준비된 이벤트가 있는지 확인한다.
selector.select();
// 셀렉터의 SelectoedSet에 저장된 준비된 이벤트들(SelectionKey)을 하나씩 처리한다. Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
if (key.isReadable()) { // 이미 연결된 클라이언트가 메시지를 보낸경우... read(key); }
// 이미 처리한 이벤트므로 반드시 삭제해준다. it.remove(); } } } catch (Exception ex) {
// log(Level.WARNING ,"SimpleChatClient.startServer()", ex); } }
}class WriteThread extends Thread { private SocketChannel sc = null; public WriteThread(SocketChannel sc) { this.sc = sc; } public void run() { ByteBuffer buffer = ByteBuffer.allocateDirect(1024); String message =null; try { sleep(400); //소켓 연결하는 동안 잠깐 대기. while (!Thread.currentThread().isInterrupted()) { sleep(5); //초당 프레임 체크
buffer.clear(); message=singletonMove.movement; //싱글톤으로 가져온 변수값
if (message.length() <2 || message==null) { //Log.e("============","===============error NULL"+message); } else {
if (message.equals("quit")|| message.equals("shutdown")) { System.exit(0); } buffer.put(message.getBytes()); buffer.flip(); sc.write(buffer);
message = null; } } } catch (Exception ex) { ex.printStackTrace(); System.exit(0); // log(Level.WARNING, "MyThread.run()", ex); } finally {
System.exit(0); clearBuffer(buffer); } } } private void read(SelectionKey key) { // SelectionKey로부터 소켓채널을 얻어온다. SocketChannel sc = (SocketChannel) key.channel(); // ByteBuffer를 생성한다. ByteBuffer buffer = ByteBuffer.allocateDirect(1024); int read = 0; try { // 요청한 클라이언트의 소켓채널로부터 데이터를 읽어들인다. read = sc.read(buffer); // info(read + " byte를 읽었습니다."); } catch (IOException ex) { try { sc.close(); } catch (IOException ex1) { } } buffer.flip(); String data = new String(); try { data = decoder.decode(buffer).toString(); } catch (CharacterCodingException ex) { // log(Level.WARNING, "SimpleChatClient.read()", ex); } System.out.println("Message - " + data); // 버퍼 메모리를 해제한다. clearBuffer(buffer); } private void clearBuffer(ByteBuffer buffer) { if (buffer != null) { buffer.clear(); buffer = null; } } } |
'Android_Programma' 카테고리의 다른 글
[ Android ] Thread 에서 Main UI 변경하기 Handler 사용하기 예제 코드 (0) | 2012.07.30 |
---|---|
[ Android ] 좀 쉽게 만든 JAVA JSON parsor CLASS (0) | 2012.07.26 |
[ Android ] Thread 에서 MainActivity UI 쓰레드 참조 시 오류와 해결법 (0) | 2012.07.26 |
[ Android ] Json 방식으로 묶기. (0) | 2012.07.18 |
[android] 영상처리 NDK 단에서 처리하여 리턴하기 (Image Processing in NDK) (5) | 2012.07.10 |