6

I'm having some troubles with the Android NDK.

My project requires software components written in C that can receive data over TCP to be executed on the Android OS.

To that end, I've made a simple server and client in C using BSD sockets and can send messages back and forth successfully across the connection on PCs. Now I've moved the clientside code into the NDK, and can't connect to my server from the emulator or from an actual android device. NDK compiles without warnings or errors, the emulator/phone are on wifi and have internet permissions enabled in the manifest. What gives?

All it does is make a socket, fill in host/port info and attempt to connect: If it does connect, send a message, else return an error. Android always returns a negative value for connect


This client code, compiled/executed on Mac/Windows/Linux, works:

PC Client code:

int tcp_socket = socket(AF_INET, SOCK_STREAM,0); 
if(tcp_socket< 0 ) {
    cerr << "Failed to create TCP socket." << endl;
    return 2;
}

sockaddr_in server_tcp_add;
server_tcp_add.sin_family = AF_INET;
server_tcp_add.sin_port = htons(tcp_port); //set via command line: Yes, they are the same for the android
hostent *hostp = gethostbyname(server_host);
memcpy(&server_tcp_add.sin_addr, hostp->h_addr, hostp->h_length); 
socklen_t slen = sizeof(server_tcp_add);

if(connect(tcp_socket,(sockaddr*)&server_tcp_add, slen) <0 ){
    cerr<< "Failed to connect to server with TCP. " << endl;
    close(tcp_socket);
    return 3;
}

char* myString = "This is my message";
send(tcp_socket, myString, strlen(myString), 0);

close(tcp_socket);

This code, executed on the Android NDK, does not

Code: NDK Client

jstring Java_networking_client_activate_initiateTcpConnection(JNIEnv* env, jobject javaThis){
    int tcp_socket = socket(AF_INET, SOCK_STREAM,0);
    if(tcp_socket < 0){
        return (*env)->NewStringUTF(env, "ERROR CREATING SOCKET");
    }
    const char* server_host = "some.numbers.that.work"; //It's a valid IP I don't feel like sharing
    unsigned short server_port = 43000;

    struct sockaddr_in server_tcp_addr;
    server_tcp_addr.sin_family = AF_INET;
    server_tcp_addr.sin_port = htons(server_port);
    struct hostent *hostp = gethostbyname(server_host);
    memcpy(&server_tcp_addr, hostp->h_addr, hostp->h_length);
    socklen_t slen = sizeof(server_tcp_addr);
    if(connect(tcp_socket,(struct sockaddr*)&server_tcp_addr, slen) < 0){ //fails here
        close(tcp_socket);
        return (*env)->NewStringUTF(env, "ERROR CONNECTING TO SERVER");
    }

    char* message = "hello from android!";
    send(tcp_socket, &message, sizeof(message),0);

    return (*env)->NewStringUTF(env, "TCP message sent!");
}

Largely identical; required to put struct in front of everything for NDK to compile.

--edit--I should also mention, I have been able to send data over sockets in Java with this app. Just the C sockets that's really screwing stuff up. Even a sample of someone else that has C sockets working via NDK would be tremendously appreciated.

3
  • Two ideas: First see if you can use something else like the web browser or netcat (nc) from the adb command line or even ping to verify you can reach the host. Second, check that you are using the right length value for all of the structures, there's one (can't remember which) that people often get wrong with the result that it can work on some implementations and not on others. Commented Feb 7, 2011 at 22:34
  • Can you check errno when connect() fails? Commented Feb 9, 2011 at 12:28
  • Left the problem alone for a few days, and came back. To respond to comments: I can use the browser on the Droid phone I am now testing on. I'm also pretty sure these are the right len functions to use. I've since accessed errno out of the NDK like __android_log_write(ANDROID_LOG_ERROR,"socket errno", strerror(errno)); and the error that is printed is "Address Family not supported by protocol". Been googling around for answers, think it might have to do with ipv6/4 problems or the hosts file on the phone. Any further help is greatly appreciated Commented Feb 17, 2011 at 2:07

1 Answer 1

13

This is a very late answer, however it might still be useful...

I changed this line:

memcpy(&server_tcp_addr, hostp->h_addr, hostp->h_length);

to this:

memcpy(&server_tcp_addr.sin_addr.s_addr, hostp->h_addr, hostp->h_length);

and that did the trick for me.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.