지금 블루트스 멀티플레이 게임을 제작중입니다.
SDK 사이트의 블루투스 채팅 샘플을 참조하고 있는데요
기본적인 기능은 됩니다면 소켓을 종료할 때가 문제가 되네요
샘플에서는 데이터 수신시 쓰레드+블록킹 방식을 사용합니다.
이게 while(true){} 안에서 블록킹되어 있습니다
그런데 이게 socket.close 를 실행시키면 항상 ioexception 을 만들어 내네요
로직을 봐서는 당연히 ioexception 이 생기는 구조 같습니다.
try catch 로 되어 있어 앱이 죽는다거나 하진 않지만
어느 책에서 봤듯이 예외처리를 이용하여 특정 기능을 수행하는 것은 잘못된 것 같습니다.
그런데 왜 공식 사이트 샘플에서는 그런 코드가 있는 건지...
실제로 하다보면 예외를 뿜어내도 제대로 되는 경우도 많지만 이후에 블루투스가 먹통이 되기도 하고...
각설하고..
예외처리를 이용하지 않고 블루투스 소켓을 정상 종료시키는 방법이 있을까요?
답변 감사합니다
그런데 종료 커맨드를 수신한다는게 무슨 의미이신지요
while (isOpen)
{
try
{
// Read from the InputStream
length = inStream.read(buffer);
byte[] trimed = new byte[length];
for (int i = 0; i < length; i++)
trimed[i] = buffer[i];
// Send the obtained bytes
// Length, Header
handlerBluetooth.obtainMessage(MyBluetooth.HANDLER_MESSAGE_RECV, length, id, trimed).sendToTarget();
}
catch (IOException e)
{
if (D)
Log.e(TAG, "disconnected", e);
Message msg = new Message();
msg.what = MyBluetooth.HANDLER_CONNECTION_LOST;
handlerBluetooth.sendMessage(msg);
break;
}
}
실제로 문제가 되는 코드인데
length = inStream.read(buffer);
에서 블로킹되어 있는 상태에서 소켓을 닫으면 예외가 발생하는 것 같습니다.
딱히 블로킹되어 있는 상태에서 빠져나올 방법이 없는 것 같더군요
그런데 어떤 네트웍 프로그램도 항상 "불미스러운"종료가 생기기 마련이기 때문에
park님께서 말씀하신 방법과 Exception 처리를 병행해야 합니다.
꼭 그렇지만은 않습니다..
왜냐면 실제로 의도적으로 예외를 발생시키는 경우도 있거든요..
예를 들어 DB를 검색했을때 관련 레코드를 찾지 못하는 그런 경우가 발생하면 사용자 정의로 만든 RecordNotFoundException 머 요런것을 만들어서 의도적으로 catch 문에 throw new RecordNotFoundException() 을 하는거죠..
그러면 그 Exception이 Strack 을 타고 계속 호출된데로 빠져나오면서 그에 따른 일관된 예외 처리를 할수 있습니다..
즉 번잡하게 if then else를 쓰는게 아니라 걍 exception 객체를 던짐으로써 특정한 상황이었을때 일관된 처리를 하게끔 하는 방법도 있습니다..
네, 일리는 있습니다
제 생각에는 말씀하신 경우는 관련 레코드가 있을 수도 있고 없을 수도 있으므로 예외가 항상 발생하는 것이라 할 수 없고,
따라서 코딩 스타일에 따라 말씀하신대로 처리할 수도 있겠죠
하지만 그... 제가 말한 샘플코드에서는
현재 상태(소켓 연결 상태?) 모르는 것이 아니고,
사용자의 명시적(?) 입력에 의해 소켓을 닫는 경우에도
항상 예외를 발생시키는 것이기에 분명히 좋은 로직은 아니라고 봅니다.
NIO 쪽을 알아보려 했지만 일반 소켓은 가능해도 블루투스 소켓은 쓸 수 없는 것 같더군요...ㅠㅠ
일반적으로 채팅같은 경우를 보자면 프로토콜을 정의해놓고 씁니다. /MSG 내용 이렇게 보면 메세지라는 것이고 내가 로그아웃 하기 위해 /LOGOUT 을 던지면 결과로 /LOGOUT 이런식으로 와서 자연스럽게 종료할 수 있고 서버측에서도 이사람이 정상적으로 종료하니 그에 맞는 처리를 할 수 있게 되는거죠 게임쪽도 크게 다르지 않겠다는 생각이 드는군요
스레드를 종료하기 위해 interrupt()를 호출해서 InterruptedException을 가로채 처리하는 경우는 많지만 소켓통신같이 블록되는 형태에서도 가능한지는 모르겠군요 (확인해보니 nio 이전의 입출력 메서드들은 interrupt()에 반응하지 않는군요)




소켓 통신할때는 써먹은 방법인데 저는 종료 커맨드를 만들어서 수신시 블럭부분을 빠져나오도록 했었습니다.