NDK 4 使用Socket与服务器通信

原创 2013年12月03日 14:53:21

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

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

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


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

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


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

package com.birds.android.ndk.socket;

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


public class DataHolder {

    public DataHolder(){
    }

    public void putData(String json) {    //Native 回调,显示数据给TextView
        MainActivity.act.updateStatus(json);
    }
}


public class MainActivity extends Activity implements View.OnClickListener {

    private TextView status;
    private volatile boolean isCon;
    public static MainActivity act;

    static {
        System.loadLibrary("network-jni");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.connect).setOnClickListener(this);
        status = (TextView) findViewById(R.id.status);
        act = this;
    }

    @Override
    public void onClick(View view) {
        if (!isCon) {
            isCon = true;
            status.setText("start connect..");
            t.start();
        }
    }

    Thread t = new Thread() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            connect();
        }
    };

    private void connect() {
        int port = 9001;
        String ip = "172.28.151.110";
        SocketJNI.doConnect(ip, port);
    }

    public void updateStatus(final String text) {
        Log.d("updateStatus", "get network data.....");
        isCon = false;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                status.setText(text);
            }
        });
    }


}

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

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

common.h

void release();
const char* connectRemote(const char*,const int);

common.c

#include "common.h"

#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>

#define  LOG_TAG    "birds_socket2"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

#define MAXSIZE 4096
struct sockaddr_in sock_add;
struct sockaddr_in server_addr;
int sockfd = 0;

void release(){
   close(sockfd);
}

const char* connectRemote(const char* addr,const int port) {
     sockfd = socket(AF_INET, SOCK_STREAM, 0);    //ipv4,TCP数据连接
     LOGI("step1");
     if (sockfd < 0) {
        return "socket error";
     }
    //remote server address
     bzero(&server_addr,sizeof(server_addr));
     server_addr.sin_family = AF_INET;
     server_addr.sin_port = htons(port);
     LOGI("step2");
     if( inet_pton(AF_INET, addr, &server_addr.sin_addr) < 0){    //set ip address
       return "address error";
     }
     socklen_t server_addr_length = sizeof(server_addr);
     int connfd = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); //连接到服务器
     LOGI("step3");
     if (connfd < 0) {
        return "connect error";
     }
     // send data
     char *msg = "i send a data to server. \n";
     int sdf = send(sockfd, msg , strlen(msg), 0); //发送一行数据到服务器
     LOGI("step4.");
     char buff[4096];
     int n = recv(sockfd, buff, MAXSIZE ,0);  //这地方应该需要循环获取数据,目前服务器只响应了一条很短的字符串。
     buff[n] = 0;
     LOGI("step5.");
     return buff;
}


下面是主JNI程序

这里不贴出生成的头文件了,直接C源码

#include "conn_socket.h"
#include "common.h"
#include <android/log.h>

#define  LOG_TAG    "birds_socket"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

 const char* getSocketData(jstring addr,jint port) { //没写,这地方占时无用
   return 0;
 }

 JNIEXPORT void JNICALL Java_com_birds_android_ndk_socket_SocketJNI_doConnect
   (JNIEnv *env, jclass jcz, jstring addr, jint port) {
       jclass jclz = (*env)->FindClass(env,"com/birds/android/ndk/socket/DataHolder");
       if (jclz) {
       	    jmethodID ins      = (*env)->GetMethodID(env,jclz,"<init>","()V");
            jobject   holdObj  = (*env)->NewObject(env,jclz,ins);
            jmethodID method1    = (*env)->GetMethodID(env,jclz,"putData","(Ljava/lang/String;)V");
            jstring msg        = (*env)->NewStringUTF(env,"has entering."); //只是个提示而已
            (*env)->CallVoidMethod(env, holdObj,method1,msg);

            LOGI("connect socket.");
            const char* response =  connectRemote("172.28.151.110",9001); //,直接hardcode,这地方没有转比较简单。
            release();
            LOGI("connect socket end.");
            msg  = (*env)->NewStringUTF(env,response);
            (*env)->CallVoidMethod(env, holdObj,method1,msg);//数据回调给DataHolder方法中
       }
  }




android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := network-jni
LOCAL_SRC_FILES := conn_socket.c \
                common.c
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)

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











版权声明:本文为博主原创文章,未经博主允许不得转载。

ndk中使用native Socket

socket进程通信命名方式有两种。一是普通的命名,socket会根据此命名创建一个同名的socket文件,客户端连接的时候通过读取该socket文件连接到socket服务端。这种方式的弊端是服务端必...
  • hb707934728
  • hb707934728
  • 2017年01月09日 14:33
  • 780

NDK Socket编程:面向连接的通信(tcp)

使用posix socket api,java层调用c层
  • hai836045106
  • hai836045106
  • 2014年10月21日 10:53
  • 8799

Android NDK Socket Hello World

本文2017-3-14   基本环境:   1. 操作系统:Windows10  64位;   2. Android Studio 2.3,64位。   3. Android NDK开发包:直接使用A...
  • gongxp123456
  • gongxp123456
  • 2017年03月14日 12:04
  • 320

Android NDK tcp例子

  • 2014年10月21日 11:01
  • 731KB
  • 下载

Android NDK中使用socket

Android NDK中使用socket的整个过程分为以下几部分: 第一部分: 创建socket并绑定IP和端口 [cpp] view plaincopy ...
  • mansir123
  • mansir123
  • 2015年11月26日 12:27
  • 512

Android利用JNI通过Socket与服务器进行通信

Android利用JNI通过Socket与服务器进行通信
  • hty1053240123
  • hty1053240123
  • 2017年08月03日 11:05
  • 917

Android NDK中socket的用法和注意事项

Android NDK中使用socket的整个过程分为以下几部分: 第一部分: 创建socket并绑定IP和端口 #include #include #include #def...
  • vrix
  • vrix
  • 2012年06月21日 11:45
  • 2378

Android原生库和架构层通信的socket

Android为原生库和架构层之间的通信提供了socket机制,在系统中为其提供了/dev/socket节点。/dev/socket节点是在init.rc文件初始化时生成的, shell@kenzo:...
  • ly890700
  • ly890700
  • 2017年01月08日 12:18
  • 1233

Android NDK网络通信篇(五)之本地通信篇

在同一个设备或者同一个APP里面,我们可以通过LocalSocket来实现本地通信,比如可以用Java代码实现一个本地通信的C/S架构的程序,也可以用Java代码实现客户端代码,用原生代码实现服务端代...
  • kgdwbb
  • kgdwbb
  • 2017年07月03日 19:21
  • 589

Android网络优化之Native Socket

众所周知,Java层已经提供一个简单易用的Socket,那为什么还要舍近求远,自己重新封装一个Native层的Socket呢?...
  • andywant2fly
  • andywant2fly
  • 2015年03月09日 16:25
  • 1885
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:NDK 4 使用Socket与服务器通信
举报原因:
原因补充:

(最多只允许输入30个字)