상황 :


공유기, 안드로이드 클라이언트, 자바 서버가 같은 로컬 네트워크로 묶여있는 상태. (자바 서버는 데스크탑)


안드로이드 클라이언트와 자바 서버는 둘 다 같은 공유기로부터 사설 아이피 주소를 할당 받아 사용중.


안드로이드 클라이언트와 자바 서버는 서로 무선 통신을 수행함.


방화벽 설정은 건들지 않았음. (켜놓은 상태)


안드로이드 클라이언트가 할당 받은 아이피 주소 : 172..30.1.3


자바 서버가 할당 받은 아이피 주소 : 172.30.1.4 (무선 네트워크로 연결)


공유기의 로컬 네트워크 주소 : 172.30.1.254


------------------------------------------------------



안드로이드 클라이언트에서 자바 서버로 소켓 연결 시도시 다음과 같은 에러가 발생하였다.






구글링을 해봐도 이 에러를 해결할 마땅한 방법을 찾지 못하는 도중에..





누군가가 안드로이드 클라이언트로 핑을 보내보라는 말을 듣고 시도를 해보았다.





맨 처음 ping은 대상 호스트에 연결 할 수 없다고 나오더니 그 이후 세 번은 모두 정상적으로 ping reply를 받았다.


그리고 나서 다시 안드로이드 클라이언트에서 자바 서버로 소켓 연결을 시도해봤더니 이번에는 되는 것이었다.


(여러 번의 테스트를 해봤는데, 항상 ping test의 결과가 처음엔 연결이 안되었다가 그 다음부터는 정상적으로 되는 


것은 아니었고, 굉장히 결과가 가변적이었다. 중요한건 ping test가 성공한 이후에 소켓 연결이 되었다는 점)



-------------------------------------------


원인 :


문제는 해결되었으나, 왜 ping을 보낸 후에 연결이 되는 것인지가 너무 궁금했다.


(나와 같은 방법으로 해결된 사람이 그 이유를 묻는 페이지를 발견했다.)


(http://stackoverflow.com/questions/14982052/why-i-can-connect-to-remote-server-but-not-to-server-in-local-network)



확실한 건 ping 시도 이후 자바 서버가 동작하는 데스크탑의 arp table 내에 안드로이드 클라이언트의 맥주소가 등


록되었다는 점, 그리고 안드로이드 클라이언트의 arp table 내에도 자바 서버가 동작하는 데스크탑의 맥 주소가 등


록되었다는 점이다.




(자바 서버가 동작하는 데스크탑의 arp table 내용 중 일부. 172.30.1.3은 안드로이드 클라이언트의 아이피)




(안드로이드 폰의 arp table 내용 중 일부. 172.30.1.4는 데스크탑(자바서버)의 아이피)




먼저 원인을 분석하기 위해서는 로컬 네트워크 상에서 두 노드간의 통신이 어떻게 이루어지는지를 알아야 한다.


원래 로컬 네트워크에 속한 두 노드가 서로 패킷을 주고 받고 하기 위해서는 서로의 맥주소를 알아야 한다.


만약 sending node의 ARP table에 이미 destination node의 맥주소가 등록되어있다면 이 맥주소를 가지고 해당


노드에게 패킷을 보내면 된다. 그런데 ARP table에 destination node의 맥주소가 없다면 ARP protocol을 이용해서


상대방의 아이피주소를 가지고 맥주소를 얻어오는 과정이 필요하다.


더 상세하게는, sending node가 destination node의 아이피 주소를 담은 ARP query packet을 MAC broadcast


address인 FF-FF-FF-FF-FF-FF로 설정해 같은 로컬 네트워크에 속한 모든 노드들에게 뿌린다. 그러면 노드들 중


에서 자신의 아이피주소와 자신이 받은 ARP query packet의 destination ip address가 일치하는 노드는 자신의 맥


주소를 sending node에게 전송해주어 sending node는 destination node의 맥주소를 알아낼 수 있는 것이다. 


이렇게 알아낸 맥주소는 sending node의 ARP table에 업데이트되며, 이제부터는 해당 노드에게 패킷을 전송할 수 


있게 된다.



이 지식을 가지고 내게 일어난 상황을 분석해보자.


맨 처음 안드로이드 클라이언트가 자바 서버에게 소켓 연결을 시도할 때에는 안드로이드 클라이언트의 arp table에


자바 서버(데스크탑)의 맥주소가 등록되어 있지 않은 상태이기 때문에 소켓 연결에서 에러가 나게 된다.


(안드로이드 클라이언트의 socket connect 메서드가 별도의 ARP request를 수행하지 않는다고 가정)


반면 자바 서버(데스크탑)가 ping test를 수행할 때에는 자바서버(데스크탑)의 ARP table에 안드로이드 클라이언트


의 맥주소가 등록되어 있지 않기 때문에 자바 서버(데스크탑)는 ARP query packet을 안드로이드 클라이언트에게


전송하여(브로드캐스팅) 안드로이드 클라이언트의 맥주소를 알아내고, 이를 ARP table에 등록한다.


(이 과정에서 안드로이드 클라이언트의 ARP table에도 자바 서버의 맥주소가 등록됨)


그리고 이 상태에서 다시 안드로이드 클라이언트가 자바 서버에게 소켓 연결을 시도하게 되면, 이 때는 안드로이드


클라이언트의 ARP table에 자바 서버의 맥주소가 등록되어 있으므로 자바 서버로의 소켓 연결이 정상적으로 이루어


지는 것이다.


여기까지 내가 분석한 상황이 정확히 맞다고 하려면 다음 사항이 맞는지 확인해야 한다.


1. ARP table에 등록되어 있지 않은 로컬 네트워크상의 노드에 대한 ping test 수행 시 ARP query packet이 전송되는


가?


2. 안드로이드 클라이언트가 ARP table에 등록되어 있지 않은 로컬 네트워크상의 노드에 대해 socket connect 메


서드를 수행하면 1번과는 달리 ARP query packet이 전송되지 않는가?



나는 아직 네트워크 패킷 캡쳐 및 분석하는 방법에 대해서 잘 모르므로(공부할 예정) 해당 부분에 대한 지식을 갖춘 후


에 내 생각이 맞는지 결과를 업데이트하려고 한다.


(1번의 경우에는 대충 구글링을 해보니 내 생각이 맞는 것 같지만 실제 테스트를 해보겠다)



----------------------------


어찌됐든 결론 :


나의 경우 같은 로컬 네트워크 망에 있는 자바 서버와 안드로이드 클라이언트에서 안드로이드 클라이언트가 자바 서


버로 소켓 연결을 시도할 때 이같은 에러가 발생한 이유는 자바 서버와 안드로이드 클라이언트 각각의 arp table에


서로의 맥주소가 등록되어 있지 않았기 때문이며, ping을 수행한 이후에는 arp table에 서로의 맥주소가 등록되기


때문에 이후부터는 소켓 연결이 가능해진다.



----------------------------


번외)


자바 서버(데스크탑)에서 안드로이드 클라이언트한테 보내는 패킷이 실제로 어떠한 경로를 거쳐서 전송되어지는지를


알아보았다. 이를 위해 두 호스트가 정상적으로 연결이 된 상태에서 tracert 명령어를 사용해보았다.




결과를 보면 무선 환경에서 데스크탑에서 스마트폰으로 패킷이 전달될 때 공유기를 거치지 않고 바로 다이렉트로 


패킷이 전달된 다는 것을 알 수 있다. 또, 나의 경우에는 데스크탑이 유선에 연결될 때에도 무선일때와 같은 로컬 네트


워크 영역에 속하길래 같은 테스트를 수행해보았는데 결과는 무선일 때와 같았다.


다만.. 이 결과가 정말로 무선 네트워크 환경에서 데스크탑이 전송하는 패킷이 공유기를 안거치고 스마트폰으로 간다


는 사실이 되는지는 모르겠다.. 즉 정확하지 않은 정보라는 점.





Posted by huammmm1
,