NDK 4 使用Socket与服务器通信

12 篇文章 0 订阅

http://blog.csdn.net/birdsaction/article/details/17095459

Android是基于Linux内核的,NDK提供的头文件基本都是 posix 协议的。 

如果熟悉Linux环境下的开发,其实做NDK会非常容易。

下面主要演示 通过JNI Socket获取服务器响应数据 并显示在UI上面。LINUX下的C 之前接触过,不过长时间不用 又生疏了。


开发工具这次使用的是:IntelliJ Community IDE

比eclipse稍微智能些。大家可以用一下。TCP服务器用的是apache mina。


首先创建项目,编写基本类.

  1. package com.birds.android.ndk.socket;  
  2.   
  3. /** 
  4.  * Created with IntelliJ IDEA. 
  5.  * To change this template use File | Settings | File Templates. 
  6.  */  
  7. public class SocketJNI {  
  8.     public native static void doConnect(String ip, int port);  
  9. }  
简单的一个JNI,内容实现是通过socket连接到服务器,获取到数据,并且设置到DataHolder类中.


  1. public class DataHolder {  
  2.   
  3.     public DataHolder(){  
  4.     }  
  5.   
  6.     public void putData(String json) {    //Native 回调,显示数据给TextView  
  7.         MainActivity.act.updateStatus(json);  
  8.     }  
  9. }  


  1. public class MainActivity extends Activity implements View.OnClickListener {  
  2.   
  3.     private TextView status;  
  4.     private volatile boolean isCon;  
  5.     public static MainActivity act;  
  6.   
  7.     static {  
  8.         System.loadLibrary("network-jni");  
  9.     }  
  10.   
  11.     @Override  
  12.     public void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         setContentView(R.layout.main);  
  15.         findViewById(R.id.connect).setOnClickListener(this);  
  16.         status = (TextView) findViewById(R.id.status);  
  17.         act = this;  
  18.     }  
  19.   
  20.     @Override  
  21.     public void onClick(View view) {  
  22.         if (!isCon) {  
  23.             isCon = true;  
  24.             status.setText("start connect..");  
  25.             t.start();  
  26.         }  
  27.     }  
  28.   
  29.     Thread t = new Thread() {  
  30.         @Override  
  31.         public void run() {  
  32.             try {  
  33.                 Thread.sleep(1000);  
  34.             } catch (InterruptedException e) {  
  35.                 e.printStackTrace();  
  36.             }  
  37.             connect();  
  38.         }  
  39.     };  
  40.   
  41.     private void connect() {  
  42.         int port = 9001;  
  43.         String ip = "172.28.151.110";  
  44.         SocketJNI.doConnect(ip, port);  
  45.     }  
  46.   
  47.     public void updateStatus(final String text) {  
  48.         Log.d("updateStatus""get network data.....");  
  49.         isCon = false;  
  50.         runOnUiThread(new Runnable() {  
  51.             @Override  
  52.             public void run() {  
  53.                 status.setText(text);  
  54.             }  
  55.         });  
  56.     }  
  57.   
  58.   
  59. }  

下面是主要的C实现的socket客户端代码,之前要生成好头文件,用javah 命令

首先编写一个socket独立的程序文件

  1. common.h  
  2.   
  3. void release();  
  4. const char* connectRemote(const char*,const int);  

  1. common.c  
  2.   
  3. #include "common.h"  
  4.   
  5. #include <string.h>  
  6. #include <sys/socket.h>  
  7. #include <netinet/in.h>  
  8. #include <stdio.h>  
  9. #include <stdlib.h>  
  10. #include <android/log.h>  
  11.   
  12. #define  LOG_TAG    "birds_socket2"  
  13. #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)  
  14.   
  15. #define MAXSIZE 4096  
  16. struct sockaddr_in sock_add;  
  17. struct sockaddr_in server_addr;  
  18. int sockfd = 0;  
  19.   
  20. void release(){  
  21.    close(sockfd);  
  22. }  
  23.   
  24. const char* connectRemote(const char* addr,const int port) {  
  25.      sockfd = socket(AF_INET, SOCK_STREAM, 0);    //ipv4,TCP数据连接  
  26.      LOGI("step1");  
  27.      if (sockfd < 0) {  
  28.         return "socket error";  
  29.      }  
  30.     //remote server address  
  31.      bzero(&server_addr,sizeof(server_addr));  
  32.      server_addr.sin_family = AF_INET;  
  33.      server_addr.sin_port = htons(port);  
  34.      LOGI("step2");  
  35.      if( inet_pton(AF_INET, addr, &server_addr.sin_addr) < 0){    //set ip address  
  36.        return "address error";  
  37.      }  
  38.      socklen_t server_addr_length = sizeof(server_addr);  
  39.      int connfd = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); //连接到服务器  
  40.      LOGI("step3");  
  41.      if (connfd < 0) {  
  42.         return "connect error";  
  43.      }  
  44.      // send data  
  45.      char *msg = "i send a data to server. \n";  
  46.      int sdf = send(sockfd, msg , strlen(msg), 0); //发送一行数据到服务器  
  47.      LOGI("step4.");  
  48.      char buff[4096];  
  49.      int n = recv(sockfd, buff, MAXSIZE ,0);  //这地方应该需要循环获取数据,目前服务器只响应了一条很短的字符串。  
  50.      buff[n] = 0;  
  51.      LOGI("step5.");  
  52.      return buff;  
  53. }  


下面是主JNI程序

  1. 这里不贴出生成的头文件了,直接C源码  
  2.   
  3. #include "conn_socket.h"  
  4. #include "common.h"  
  5. #include <android/log.h>  
  6.   
  7. #define  LOG_TAG    "birds_socket"  
  8. #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)  
  9.   
  10.  const char* getSocketData(jstring addr,jint port) { //没写,这地方占时无用  
  11.    return 0;  
  12.  }  
  13.   
  14.  JNIEXPORT void JNICALL Java_com_birds_android_ndk_socket_SocketJNI_doConnect  
  15.    (JNIEnv *env, jclass jcz, jstring addr, jint port) {  
  16.        jclass jclz = (*env)->FindClass(env,"com/birds/android/ndk/socket/DataHolder");  
  17.        if (jclz) {  
  18.             jmethodID ins      = (*env)->GetMethodID(env,jclz,"<init>","()V");  
  19.             jobject   holdObj  = (*env)->NewObject(env,jclz,ins);  
  20.             jmethodID method1    = (*env)->GetMethodID(env,jclz,"putData","(Ljava/lang/String;)V");  
  21.             jstring msg        = (*env)->NewStringUTF(env,"has entering."); //只是个提示而已  
  22.             (*env)->CallVoidMethod(env, holdObj,method1,msg);  
  23.   
  24.             LOGI("connect socket.");  
  25.             const char* response =  connectRemote("172.28.151.110",9001); //,直接hardcode,这地方没有转比较简单。  
  26.             release();  
  27.             LOGI("connect socket end.");  
  28.             msg  = (*env)->NewStringUTF(env,response);  
  29.             (*env)->CallVoidMethod(env, holdObj,method1,msg);//数据回调给DataHolder方法中  
  30.        }  
  31.   }  




android.mk

  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_MODULE    :network-jni  
  4. LOCAL_SRC_FILES :conn_socket.c \  
  5.                 common.c  
  6. LOCAL_LDLIBS += -llog  
  7. include $(BUILD_SHARED_LIBRARY)  

如果熟悉Linux开发,上面的程序非常简单。有很多地方还是需要改善的。












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值