Android JNI 개발 중 소켓 연결에서 예기치 않은 오류가 발생했습니다. socket() 함수 호출 시 지속적으로 오류가 반환되었습니다.
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
debug(LEVEL_ERROR, "Socket creation failed with error %d\r\n", errno);
return -1;
}
출력된 오류 코드는 64였으며, 해당 에러 메시지는 "Machine is not on the network"입니다. 이는 프로세스가 현재 네트워크에 연결되어 있지 않다고 간주됨을 의미합니다.
오류 상황 분석
디바이스는 이더넷 케이블이 연결되어 있고 IP가 정상적으로 할당된 상태였습니다. PC에서 Android 디바이스로 UDP 통신은 정상적으로 이루어졌으나, TCP 통신만 위 오류가 발생했습니다. 이는 네트워크 설정과 관련된 문제로 추정되었습니다.
초기화 과정에서 이더넷 네트워크에 프로세스를 바인딩하는 코드가 있었습니다:
public static boolean bindProcessToEthernet(Context ctx) {
Network defaultNet = ConnectivityManager.getProcessDefaultNetwork();
if (defaultNet != null) {
Log.d("=== Current process network: " + defaultNet.toString());
}
// 기존 바인딩 해제
ConnectivityManager.setProcessDefaultNetwork(null);
ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] allNetworks = cm.getAllNetworks();
if (allNetworks != null) {
for (Network net : allNetworks) {
Log.d("=== Network found: " + net.toString());
NetworkInfo info = cm.getNetworkInfo(net);
if (info != null && info.getType() == ConnectivityManager.TYPE_ETHERNET) {
Log.d("=== Binding to Ethernet network.");
return ConnectivityManager.setProcessDefaultNetwork(net);
}
}
}
Network currentNet = ConnectivityManager.getProcessDefaultNetwork();
if (currentNet != null) {
Log.d("=== After binding: " + currentNet.toString());
}
return false;
}
해결 방법
디바이스가 정상 부팅되고 네트워크가 연결된 후, 위 함수가 실행되어 현재 네트워크를 강제로 이더넷에 고정했습니다. 이 과정에서 TCP 연결이 오히려 차단되는 현상이 발생했습니다. 문제 해결을 위해 네트워크 바인딩을 초기화하는 방법이 효과적이었습니다:
// 프로세스의 네트워크 바인딩 해제
ConnectivityManager.setProcessDefaultNetwork(null);
이렇게 하면 애플리케이션이 시스템의 기본 네트워크 정책에 따라 자동으로 적절한 네트워크를 선택하게 되어 TCP 통신이 정상화됩니다.
단, Wi-Fi나 모바일 네트워크 등 여러 네트워크 인터페이스가 존재하는 환경에서는 시스템이 자동으로 적절한 우선순위로 전환하지 않을 수 있으므로, 필요에 따라 네트워크 우선순위를 명시적으로 구성해야 할 수 있습니다.