LocalSocket实现进程间通信

LocalSocket实现进程间通信

android下使用localsocket可以实现C与C,C与JAVA,JAVA与JAVA进程间通信。
localsocket是linux下的一种本地套接字,用来进行进程间通信,分为非命名和命名两种类型,非命名本地套接字只能用在父子进程之间通信(其实是只有保存了未命名的套接字的文件描述符的进程可以使用),命名套接字则没有这个限制。android在linux的本地套接字上进行封装。
android上使用localsocket主要是通过name来区分,也就是说客户端和服务端之间连接必须使用相同的name,并且一个name同一时间只能有一个服务端运行,name可以只一串字符串,如“com.penguin.sk”。

  • c 客户端
  • c 服务端
  • java 客户端
  • java 服务端

c 客户端

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 服务端

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 客户端

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 := factory
include $(BUILD_JAVA_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := clientSocketJava
LOCAL_SRC_FILES := clientSocket
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)

clientSocket 脚本

#!/system/bin/sh
#
# Script to start "" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/factory.jar
exec app_process $base/bin com.android.commands.factory.Factory "$@"

java 服务端

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();
            }

        }
    }

}

目录

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值