Android 系统中运行独立 c 语言 udp 程序

来源:互联网 发布:东北大学奥鹏网络教育 编辑:程序博客网 时间:2024/06/06 21:18

    在 Android 软件开发中,使用 c 语言编程的 JNI(Java Native Interface)技术,无疑是提高软件性能和功能的一个很好选择。如何安装和使用 JNI 在网络上有很多介绍,但如何运行独立的纯 c/c++ 语言程序,却鲜有提及。然而,一个独立的纯 c/c++ 语言程序,在按模块编程、调试的过程中,又要求它能够在 Android 系统中独立运行。
    文本的目的有两个:一是演示如何在一个 Android 系统中,编译、连接和运行一个支持 c 语言程序,而不是 JNI;第二是演示一个简单的 udp 客户程序,是如何完成与 Windows 端服务器程序的 udp 通信的。
    Android 系统支持 JNI,当然也支持 c 语言程序。下面就是一个运行在Android系统中的纯 c 语言 udp 客户程序:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

InitSock(int thePort, char *addr, char *buf)
{
 int m_socket = socket(AF_INET, SOCK_DGRAM, 0); 

 struct sockaddr_in toHost;
 memset(&toHost, 0, sizeof(struct sockaddr_in)); 

 inet_aton(addr,&toHost.sin_addr);
 toHost.sin_family = AF_INET;
  toHost.sin_port = htons(thePort); 

 int fromlen = sizeof(struct sockaddr_in);
        int len = strlen(buf);

 sendto(m_socket, buf, len ,0, (struct sockaddr *)&toHost, fromlen);
}

int main(int argc, char *argv[])
{
 InitSock(3456, "10.0.2.2", "abcdefgh");  
 return 0;
}

    这个 c 语言 udp 客户程序实际上已经在 linux 系统环境调试过。做过socket网络程序的朋友对这些语句都会比较熟悉,这里就不解释了。只是"10.0.2.2"这个地址,是 Android模拟器提供访问我们 Windows 电脑本机的地址。

    独立的c程序有了,怎么运行呢?Android 软件的开发环境普遍采用Eclipse,我们的c程序也要在Eclipse环境下运行。
在Eclipse下怎样安装配置Android 软件的开发环境你一定已经做好了,下载和安装NDK你也应该做好了,我们这里就不再啰嗦。下面就是运行我们的c程序的步骤:
1. 新建一个目录,我们的项目就在这个目录之下。目录名是udpclient。
2. udpclient目录下再建立一个目录,取名jni,注意这个目录名字不是用户自定义的。用其它名字的话,我们的项目就找不到c程序了。

3. 把我们的c程序放到jni目录下,还要在这个目录下新建一个Android.mk文件。Android.mk文件如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hSock
LOCAL_SRC_FILES := udpclient.c

include $(BUILD_EXECUTABLE)

    解释一下:第一、二条语句是固定格式,第三句是产生的可执行文件取名hSock,第四句指定源文件,最后一条BUILD_EXECUTABLE 是产生可执行文件(JNI程序不是可执行文件,注意这里不同)。

4. 进入命令提示符状态(控制台,或者DOS状态)。先进入项目目录,命令是(我们的项目在F盘Android\Java目录之下):
cd F:\Android\Java\udpclient(回车)

注意后面的命令之后都要跟一个回车,命令才起作用。

5. 在项目目录中执行ndk-build编译命令(注意我的NDK是android-ndk-r7,安装在F:\Program\Java\Android\目录下):
F:\Android\Java\udpclient>F:\Program\Java\Android\android-ndk-r7\ndk-build(回车)

正常情况下,应该出现如下提示符,表示我们编译正常,产生了一个叫hSock的可执行文件:
"Compile thumb : hSock <= udpclient.c
Executable     : hSock
Install        : hSock => libs/armeabi/hSock

hSock可执行文件的所在目录:
F:\Android\Java\udpclient\obj\local\armeabi

注意这是一个Android系统可执行文件,只能Android系统下运行。所以,我们要进入Android系统环境。

6. 首先运行任意Eclipse程序,以进入Android模拟器系统环境。再把执行文件从pc机上复制到模拟机上,这需要使用模拟器的传输命令。而模拟器命令在Android的sdk之中。进入模拟器执行文件目录platform-tools。我的SDK安装在F:\Program\Java\Android 目录下。输入命令:
cd F:\Program Files\Android\android-sdk\platform-tools(回车)

下面的命令adb push把文件从pc机上复制到模拟机内存的test目录中(我已经先建立了这个目录)。命令是:
F:\Program Files\Android\android-sdk\platform-tools>adb push F:\VC\Android\Java\udpclient\obj\local\armeabi\hSock /data/data/test/

7. 进入shell命令模式,再进入模拟器内存的test目录,再修改hSock为可执行文件属性,最后执行hSock.这四步是四条命令:
F:\Program Files\Android\android-sdk\platform-tools>adb shell
#cd /data/data/test
#chmod 777 hSock
#./hSock

后三条是shell命令。这样我们的c程序就运行起来了。但是,看不到结果。因为我们的c程序只是 udp 客户程序,要看到数据是不是传输成功,还应该有一个服务器程序。下面就是一个简单的 Windows 控制台 c 语言 udp 服务器程序:

int Connecting(int thePort)
{

 WSADATA wsaData;
 WSAStartup(0x202,&wsaData);

 SOCKET m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

 struct sockaddr_in m_local;
 memset(&m_local, 0, sizeof(sockaddr_in));
 m_local.sin_family = AF_INET; 
 m_local.sin_addr.s_addr = htonl(INADDR_ANY);
  m_local.sin_port = htons(thePort);

 if(bind(m_socket ,(struct sockaddr *)&m_local ,sizeof(struct sockaddr_in)) < 0)  
 {
  printf("bind error..."); 
  return -1;
 }

 char pInput[100];
 int m_bufLen = 100;
 unsigned int len = sizeof(sockaddr_in); 
 struct sockaddr_in m_fromHost;
 memset(&m_fromHost, 0, sizeof(struct sockaddr_in));

 int ret = recvfrom(m_socket, pInput, m_bufLen, 0, (struct sockaddr*)&m_fromHost, (socklen_t*)&len);
 printf("read = %s\n", pInput); 

 return ret;
}

int _tmain(int argc, _TCHAR* argv[])
{
 int k = Connecting(3456);

 return k;
}

这是一个vc 控制台程序。先运行这个 Windows 端的 udp 服务器程序,再到 Android 系统中执行./hSock命令。

    这样,就实现了我们的 Android 系统向 Windows 系统发送通知的目的。
    看起来,好像运行一个Android 的 c 语言程序比较复杂,其实,这里很多都是 linux 系统常用的命令。只要我们熟悉 linux 系统,上面的内容很好掌握。
下面可以下载这个执行程序:
http://download.csdn.net/detail/ohorse6/8028497

0 0