android下使用localsocket可以实现C与C,C与JAVA,JAVA与JAVA进程间通信。
localsocket是linux下的一种本地套接字,用来进行进程间通信,分为非命名和命名两种类型,非命名本地套接字只能用在父子进程之间通信(其实是只有保存了未命名的套接字的文件描述符的进程可以使用),命名套接字则没有这个限制。android在linux的本地套接字上进行封装。
android上使用localsocket主要是通过name来区分,也就是说客户端和服务端之间连接必须使用相同的name,并且一个name同一时间只能有一个服务端运行,name可以只一串字符串,如“com.penguin.sk”。
c客户端代码主要调用的是android接口:
int socket_local_server(const char *name, int namespaceId, int type)
函数读写id,read id就是接收服务端的数据,write id就是发送数据给服务端– 参数name就是上述说的客户端与服务端连接的关键name,namespaceId一般使用ANDROID_SOCKET_NAMESPACE_ABSTRACT, type 使用SOCK_STREAM。下面是客户端c demon代码:
#include <sys/socket.h>#include <sys/un.h>#include <stddef.h>#include <string.h>#include <unistd.h>#include <stdio.h>#include <cutils/sockets.h>#define PATH "com.penghui.localsocket"int main(int argc, char *argv[]) { int socketID; int ret; int i = 0; int len = 0; for(;i < argc ;i++){ len = len + strlen(argv[i]); } len = len + argc ; char *buffer ; buffer = ( char *)malloc(len * sizeof( char *)); if(buffer == NULL){ printf("malloc failed\n"); return 0; } strcpy(buffer, argv[0]); for(i=1;i<argc;i++){ strcat(buffer, " "); strcat(buffer, argv[i]); } socketID = socket_local_client(PATH, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); if (socketID < 0) { return socketID; } ret = write(socketID, buffer, strlen(buffer)); if(ret < 0){ printf("send failed\n"); return ret; } char buf2[512] = {0}; ret = read(socketID,buf2,sizeof(buf2)); if(ret < 0){ printf("recived failed\n"); return ret; }else{ printf("c client recived from server: %s\n",buf2); } ret = close(socketID); if (ret < 0) { return ret; } return 0;}
c服务端调用
int socket_local_server(const char *name, int namespace, int type)
函数返回服务端socket,然后可以调用accept开始接受客户端请求,参数与客户端一样
#include <sys/socket.h>#include <sys/un.h>#include <stddef.h>#include <string.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <cutils/sockets.h>#include <pthread.h>#define PATH "com.penghui.localsocket"void * connectThread(void *arg);int main(int argc, char *argv[]){ int ret ; int serverID = socket_local_server(PATH, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); if(serverID < 0){ printf("socket_local_server failed :%d\n",serverID); return serverID; } int socketID; pthread_t tid; while((socketID= accept(serverID,NULL,NULL)) >=0){ ret = pthread_create(&tid,NULL,connectThread,(void *)&socketID); if(ret != 0){ printf("error create thread:%s\n",strerror(ret)); exit(1); } } return ret;}void * connectThread(void *arg){ int ret; int socketID =*(int *)arg; if(socketID < 0){ printf("socketID is %d\n",socketID); return NULL; } char buf2[512] = {0}; ret = read(socketID,buf2,sizeof(buf2)); if(ret < 0){ printf("recived failed\n"); return NULL; } printf("c server recived: %s\n",buf2); char buffer[] = {"this message from c server "}; ret = write(socketID, buffer, strlen(buffer)); if(ret < 0){ printf("write failed\n"); return NULL; } close(socketID); return NULL;}
java 的服务端和客户端和网络socket基本一样,只不过网络socket是用ip和端口号连接的,localsocket使用上述说的name。
客户端代码是在android源码下编译成jar包,然后仿造android am命令(frameworks/base/cmds/am/)在clientSocket脚本里调用jar包做成可执行文件的,这种做法对jar包的包名有要求,最好是直接用com.android.commands.*开头的。
package com.android.commands.factory;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import android.net.LocalSocket;import android.net.LocalSocketAddress;import android.util.Log;public class Factory { private static final String TAG= "Factory_test"; public static void main(String[] args){ if(args.length == 0 ){ printHelp(); return ; } String command = ""; for(int i = 0;i < args.length; i++){ command = command + args[i] + " "; Log.w(TAG,"command"+command); } ClientConnect cl = new ClientConnect(); cl.connect(); cl.send(command); String result = cl.recv(); System.out.println("java client recive:"+result); cl.close(); } private static void printHelp(){ System.out.println( "\n" + "Usage: factory_test cmds [params]\n" + "cmds:\n" + " get_eth_mac -- get ethernet mac address.\n" + " copy_log -- copy the log to usb device .\n" ); }}class ClientConnect { private static final String TAG = "ClientConnect"; private static final String name = "com.penghui.localsocket"; private LocalSocket Client = null; private PrintWriter os = null; private BufferedReader is = null; private int timeout = 30000; public void connect(){ try { Client = new LocalSocket(); Client.connect(new LocalSocketAddress(name)); // Client.setSoTimeout(timeout); } catch (IOException e) { e.printStackTrace(); } } public void send(String data) { try { os = new PrintWriter(Client.getOutputStream()); os.println(data); os.flush(); //System.out.println("client send over"); } catch (IOException e) { e.printStackTrace(); } } public String recv() { Log.d(TAG,"recv"); String result = null; try { is = new BufferedReader(new InputStreamReader(Client.getInputStream())); result = is.readLine(); Log.d(TAG, result); } catch (IOException e) { e.printStackTrace(); } finally { } return result; } public void close() { try { is.close(); os.close(); Client.close(); } catch (IOException e) { e.printStackTrace(); } } }
Android.mk
# Copyright 2008 The Android Open Source Project#LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := $(call all-subdir-java-files)LOCAL_MODULE := factoryinclude $(BUILD_JAVA_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := clientSocketJavaLOCAL_SRC_FILES := clientSocketLOCAL_MODULE_CLASS := EXECUTABLESLOCAL_MODULE_TAGS := optionalinclude $(BUILD_PREBUILT)
clientSocket 脚本
#!/system/bin/sh## Script to start "" on the device, which has a very rudimentary# shell.#base=/systemexport CLASSPATH=$base/framework/factory.jarexec app_process $base/bin com.android.commands.factory.Factory "$@"
java服务端实现在一个apk里,apk启动时开启服务端,然后就可以执行客户端命令去与服务端交互数据。
package com.example.localsocketserver;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import android.app.Activity;import android.net.Credentials;import android.net.LocalServerSocket;import android.net.LocalSocket;import android.net.LocalSocketAddress;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private ServerThread mThread = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startServer(); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); stopServer(); } private void startServer(){ stopServer(); mThread = new ServerThread(); mThread.start(); } private void stopServer(){ if(mThread != null){ mThread.exit(); mThread = null; } } private class ServerThread extends Thread{ private boolean exit = false; private int port = 3333; public void run() { LocalServerSocket server = null; BufferedReader mBufferedReader = null; PrintWriter os = null; String readString =null; try { server = new LocalServerSocket("com.repackaging.localsocket"); while (!exit) { LocalSocket connect = server.accept(); Credentials cre = connect.getPeerCredentials(); Log.i(TAG,"accept socket uid:"+cre.getUid()); new ConnectThread(connect).start(); } } catch (IOException e) { e.printStackTrace(); }finally{ try { mBufferedReader.close(); os.close(); server.close(); } catch (IOException e) { e.printStackTrace(); } } } public void exit(){ exit = true; this.interrupt(); try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class ConnectThread extends Thread{ LocalSocket socket = null; BufferedReader mBufferedReader = null; InputStream input = null; PrintWriter os = null; String readString =null; public ConnectThread(LocalSocket socket){ this.socket = socket; } @Override public void run(){ try { input = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = input.read(buffer); Log.d(TAG,"mBufferedReader:"+new String(buffer,0,len)); /* while((readString=mBufferedReader.readLine())!=null){ //if(readString.equals("finish")) // break; Log.d(TAG,"server recive :"+readString); break; } */ os = new PrintWriter(socket.getOutputStream()); os.println("this is server\0"); os.flush(); os.close(); socket.close(); Log.d(TAG,"server send over"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
联系客服