2011-05-17 23 views
15

içinde bir doğal C programında aşağıdaki satırın ilgili bir soru vardır:kullanarak Soket() Android NDK

#include <sys/socket.h> 
#include <errno.h> 

void testSocket() 
{ 
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    int err = errno; 
} 

soket oluşturulacak başarısız (sockfd = 1) ve errno = 13. benim Manifestosunun tanımlanan aşağıdaki adres:

<uses-permission android:name="android.permission.INTERNET"/> 

kimse bana bu işe yaramaz neden/bilgi var herhangi bir deneyime söyleyebilir misiniz? Bu noktada boşlukları çekiyorum.

+0

Herhangi bir fark üçüncü argüman IPPROTO_TCP ise rence? Ayrıca bkz. Http://stackoverflow.com/questions/5279076/granting-android-application-the-android-permission-internet-permission-while-deb – fadden

cevap

2
<uses-permission android:name="android.permission.INTERNET" /> 
the application tag in your AndroidManifest.xml 
注意放置的位置; 
如下:my AndroidManifest.xml 
--------------------------------------- 
<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="org.eshock.jnitest" 
     android:versionCode="1" 
     android:versionName="1.0"> 
    <uses-permission android:name="android.permission.INTERNET" /> 
    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
     <activity android:name=".JNITest" 
        android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

    </application> 
</manifest> 
dışında uygulama etiketi

<uses-permission android:name="android.permission.INTERNET" /> 

12
Application.mk 
-------------- 
APP_PROJECT_PATH := $(call my-dir) 
APP_MODULES  := mylib 

#-------------------------------------------------------------------------------- 

【以下是几个c文件】 
NativeHello.c ,主要的C文件,调用其它普通linux native c 
----------------------------------------------------- 
#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 
#include <jni.h> 
#include <assert.h> 
#include "HttpGet.h" 

JNIEXPORT jstring JNICALL native_hello(JNIEnv *env, jclass clazz) 
{ 
    printf("hello in c native code./n"); 
    mmain(); 
    return (*env)->NewStringUTF(env, "-------------hello world mmain().-------------"); 
} 

#define JNIREG_CLASS "org/eshock/jnitest/JNITest"//指定要注册的类 
         //注意:是类名 
/** * Table of methods associated with a single class. */ 

static JNINativeMethod gMethods[] = { 
     { "hello", "()Ljava/lang/String;", (void*)native_hello },//绑定 
     }; /* * Register several native methods for one class. */ 

static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) 
{ 
    jclass clazz; 
    clazz = (*env)->FindClass(env, className); 
    if (clazz == NULL) 
    { 
     return JNI_FALSE; 
    } 
    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) 
    { 
     return JNI_FALSE; 
    } 

    return JNI_TRUE; } 

/* * Register native methods for all classes we know about. */ 
static int registerNatives(JNIEnv* env) 
{ 
    if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods)/sizeof(gMethods[0]))) 
    { 
     return JNI_FALSE; 
    } 
    return JNI_TRUE; 
} 

/* * Set some test stuff up. * * Returns the JNI version on success, -1 on failure. 
*当Android的VM(Virtual Machine)执行到System.loadLibrary()函数时,首先会去执行C组件里的JNI_OnLoad()函数。 
*它的用途有二: 
*(1)【版本】告诉VM此C组件使用那一个JNI版本。如果你的*.so档没有提供JNI_OnLoad()函数,VM会默认该*.so档是使用最老的JNI 1.1版本。 
* 由于新版的JNI做了许多扩充,如果需要使用JNI的新版功能,例如JNI 1.4的java.nio.ByteBuffer, 
* 就必须藉由JNI_OnLoad()函数来告知VM。 
*(2)【初始化】由于VM执行到System.loadLibrary()函数时,就会立即先呼叫JNI_OnLoad(),所以C组件的开发者可以藉由JNI_OnLoad() 
* 来进行C组件内的初期值之设定(Initialization) 。 
    * */ 

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) 
{ 
    JNIEnv* env = NULL; 
    jint result = -1; 
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) 
    { 
     return -1; 
    } 
    assert(env != NULL); 
    if (!registerNatives(env))//注册 
    { 
     return -1; 
    } 
    /* success -- return valid version number */ 
    result = JNI_VERSION_1_4; 
    return result; 
} 

-------------------------------------------- 
HttpGet.c 
#include "HttpGet.h" 
#include <android/log.h> 

int GetHttpResponseHead(int sock,char *buf,int size) 
{ 
    int i; 
    char *code,*status; 
    memset(buf,0,size); 
    for(i=0; i<size-1; i++){ 
     if(recv(sock,buf+i,1,0)!=1){ 
      perror("recv error"); 
      return -1; 
     } 
     if(strstr(buf,"\r\n\r\n")) 
      break; 
    } 
    if(i >= size-1){ 
     puts("Http response head too long."); 
     return -2; 
    } 
    code=strstr(buf," 200 "); 
    status=strstr(buf,"\r\n"); 
    if(!code || code>status){ 
     *status=0; 
     printf("Bad http response:\"%s\"\n",buf); 
     return -3; 
    } 
    return i; 
} 

int HttpGet(const char *server,const char *url) 
{ 
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter HttpGet function!"); 
    int sock=socket(PF_INET,SOCK_STREAM,0); 
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "%d",sock); 
    struct sockaddr_in peerAddr; 
    char buf[2048]; 
    int ret; 
    //const char *filename; 
    //FILE *fp=NULL; 
    peerAddr.sin_family=AF_INET; 
    peerAddr.sin_port=htons(80); 
    peerAddr.sin_addr.s_addr=inet_addr(server); 
    ret=connect(sock,(struct sockaddr *)&peerAddr,sizeof(peerAddr)); 
    if(ret != 0){ 
     perror("connect failed"); 
     close(sock); 
     return -1; 
    } 
    sprintf(buf, 
     "GET %s HTTP/1.1\r\n" 
     "Accept: */*\r\n" 
     "User-Agent: [email protected]\r\n" 
     "Host: %s\r\n" 
     "Connection: Close\r\n\r\n", 
     url,server); 
    send(sock,buf,strlen(buf),0); 
    if(GetHttpResponseHead(sock,buf,sizeof(buf))<1){ 
     close(sock); 
     return -1; 
    } 
    //filename=strrchr(url,'/')+1; 
    //if(!filename[0]) 
     //filename="index.html"; 
    //fp=fopen(filename,"wb"); 
    //if(fp) 
    //{ 
     __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter HttpGet function's while!"); 
     while((ret=recv(sock,buf,sizeof(buf),0)) > 0) 
     { 
      //fwrite(buf,ret,1,fp); 
      __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "hello, this is my number %s log message!", buf); 
     } 
    //} 
    //fclose(fp); 
    shutdown(sock,SHUT_RDWR); 
    close(sock); 
    return 0; 
} 

//"http://192.168.7.222/index.html" 
int mmain(void) 
{ 
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter mmain function!"); 
    char *head,*tail; 
    char server[128]={0}; 
/* if(argc<2){ 
     printf("Usage:%s url\n",argv[0]); 
     return -1; 
    } 
    if(strlen(argv[1])>1500){ 
     puts("Url too long."); 
     return -1; 
    }*/ 
    //head=strstr("http://192.168.10.101/gi/1.html","//"); 
    head=strstr("http://220.181.111.148/index.html","//"); 
    if(!head){ 
     puts("Bad url format"); 
     return -1; 
    } 
    head+=2; 
    tail=strchr(head,'/'); 
    if(!tail){ 
     return HttpGet(head,"/"); 
    }else if(tail-head>sizeof(server)-1){ 
     puts("Bad url format"); 
     return -1; 
    }else{ 
     memcpy(server,head,tail-head); 
     return HttpGet(server,tail); 
    } 
} 

HttpGet.h 
--------------------------- 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <fcntl.h> 
#include <ctype.h> 
#include <unistd.h> 
#include <netdb.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 

int GetHttpResponseHead(int sock,char *buf,int size); 
int HttpGet(const char *server,const char *url); 
int mmain(void); 

android.mk 
-------------------- 

include $(CLEAR_VARS) 
LOCAL_LDLIBS := -lm -llog 
LOCAL_SHARED_LIBRARIES := liblog libcutils 

LOCAL_MODULE := mylib 
LOCAL_SRC_FILES := \ 
    NativeHello.c \ 
    HttpGet.h \ 
    HttpGet.c \ 

include $(BUILD_SHARED_LIBRARY) 
#-------------------------------------------------------------------------------- 
+0

Wow! Bu örnek için çok teşekkürler! – giuliolunati