android socket通讯
项目中要用到进程间通讯,服务端接收应用的请求数据,对串口进行读写操作。考虑到android的socket服务比较实用,并且可以支持多个客户端同时连接。
服务端写成一个服务,在init.rc中启动,示例代码如下:
socket_keyboard.c:
#define LOG_TAG "socket-keyboard"#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <utime.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cutils/fs.h>
#include <cutils/sockets.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>
#define SOCKET_PATH "spi-keyboard"
//#define ALOGE LOGEvoid *thr_fn(void *arg)
{int s = (int)arg;char buf[1024];int count;char *respone = "this is from service";ALOGE("new thread: ");while (1) {ALOGE("read...");count = read(s,buf, sizeof(buf));if (count > 0) {buf[count] = '\0';ALOGE("read client:%s", buf);if (!memcmp(buf, "close", 5))break;}ALOGE("write...");count = write(s, respone, strlen(respone));}return NULL;
}int main(const int argc, const char *argv[]) {struct sockaddr addr;socklen_t alen;int lsocket, s;ALOGE("socket keyboard service start");lsocket = android_get_control_socket(SOCKET_PATH);if (lsocket < 0) {ALOGE("Failed to get socket from environment: %s\n", strerror(errno));exit(1);}if (listen(lsocket, 5)) {ALOGE("Listen on socket failed: %s\n", strerror(errno));exit(1);}ALOGE("socket keyboard service loop......");for (;;) {ALOGE("accept...");alen = sizeof(addr);s = accept(lsocket, &addr, &alen);if (s < 0) {ALOGE("Accept failed: %s\n", strerror(errno));continue;} else {int err;pthread_t ntid;err = pthread_create(&ntid, NULL, thr_fn, (void *)s);} }ALOGE("service close");return 0;
}
客户端可以是c/c++代码,也可以是应用层代码,c代码如下:
#define LOG_TAG "socket-client"#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <utime.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cutils/fs.h>
#include <cutils/sockets.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <cutils/multiuser.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <sys/un.h>
#include <errno.h>
#include <private/android_filesystem_config.h>
#define SOCKET_PATH "socket-keyboard"#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
int main(const int argc, const char *argv[]) {char buf[1024] = {0};struct sockaddr_un addr;struct sockaddr_un *p_addr;socklen_t alen;int fd, s, count;size_t namelen;char *str = "this is from client";char *name = "spi-keyboard";p_addr = &addr;memset (p_addr, 0, sizeof (*p_addr));strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);strcat(p_addr->sun_path, name);p_addr->sun_family = AF_LOCAL;namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;ALOGE("socket keyboard client start");fd = socket(PF_LOCAL, SOCK_STREAM, 0);if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {ALOGE("connet spi keyboard server err[%s]", strerror(errno));exit(-1);} while (1) {ALOGE("write");write(fd, str, strlen(str) + 1);ALOGE("read");count = read(fd, buf, sizeof(buf));if (count) {ALOGE("client: %s", buf);}sleep(1);}return 0;
}
客户端的c代码是仿照android socket源代码搬写过来的,源代码路径在system/core/libcutils/socket_local_client.c中。
Android.mk:
LOCAL_PATH := $(call my-dir)
#
# Executable
#include $(CLEAR_VARS)
LOCAL_SRC_FILES := \socket_keyboard.cLOCAL_SHARED_LIBRARIES := \libcutilsLOCAL_STATIC_LIBRARIES := \libdiskusage
LOCAL_MODULE := spi-keyboardLOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE)include $(CLEAR_VARS)
LOCAL_SRC_FILES := \socket_client.cLOCAL_SHARED_LIBRARIES := \libcutilsLOCAL_STATIC_LIBRARIES := \libdiskusage
LOCAL_MODULE := socket-clientLOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE)
把编译出来的执行文件放入/system/bin/目录,接着在init.rc中加入启动服务:
service spi-keyboard /system/bin/spi-keyboardclass mainsocket spi-keyboard stream 777 user user
这里权限要更改成777 和 user,否则应用程序没有权限连接该服务。系统启动后在/dev/socket/目录下发现多了一个文件:
adbd keystore property_service spi-keyboard
dnsproxyd mdns rild vold
installd netd rild-debug zygote
这就是新的socket服务spi-keyboard。
执行./socket_client 即可连接上服务端。
应用层代码如下:
package com.example.keyboardsocketclient;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;public class MainActivity extends Activity {LocalSocket mSocket;InputStream mIn;OutputStream mOut;byte buf[] = new byte[1024];int ret = 0;String write_str = "this is from client******************************************";String write_str1 = "close";ServerSocketThread mthread;boolean isInterrupted = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mthread = new ServerSocketThread();mthread.start();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}@Overrideprotected void onDestroy() { Log.d("spi-keyboard", "onDestroy");super.onDestroy();mthread.interrupt();finish();} void connect() throws IOException {//创建socketmSocket = new LocalSocket();//设置连接地址LocalSocketAddress address = new LocalSocketAddress("spi-keyboard", LocalSocketAddress.Namespace.RESERVED);//建立连接mSocket.connect(address);//获取数据输入流 可以读数据mIn = mSocket.getInputStream();//获取数据输出流 可以写数据mOut = mSocket.getOutputStream();}private class ServerSocketThread extends Thread {public void interrupt(){isInterrupted = true;super.interrupt();}@Overridepublic void run() {try {connect();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}while (!isInterrupted) {//不能用this.isInterrupted()来判断,因为sleep时候,中断线程,只会catch异常,接着下一次循环中isInterrupted()还是为false try {Thread.sleep(1000);//括号里面的5000代表5000毫秒,也就是5秒,可以该成你需要的时间} catch (InterruptedException e) {e.printStackTrace();}try {mOut.write(write_str.getBytes());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}int count = 0;while (count == 0) {try {count = mIn.available();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}byte[] b = new byte[count];try {ret = mIn.read(b);} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}if (ret > 0) {String str = "";try {str = new String(b, "UTF-8");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}Log.e("keyboard client", "" + str);}}}}
}
运行该apk可以发现,服务端又为这个客户端创建一个线程,这样两个客户端可以同时连接,要注意LocalSocketAddress的第二个参数必须为LocalSocketAddress.Namespace.RESERVED,这个值为1,android专门为路径/dev/socket通讯而留的。
android socket通讯相关推荐
- Protobuf实现Android Socket通讯开发教程
本节为您介绍Protobuf实现Android Socket通讯开发教程,因此,我们需要先了理一下protobuf 是什么? Protocol buffers是一种编码方法构造的一种有效而可扩展的格式 ...
- Android Socket通讯 之 心跳消息
心跳消息 前言 正文 一.状态判断 二.心跳消息发送 三.心跳消息回复 四.源码 前言 不知道大家国庆节过的咋样,有没有学习呢?我是闲着没事就写点东西,本文篇幅较短,只是实现了心跳消息的处理,下面 ...
- android okhttpclient设置编码,Android之okhttp实现socket通讯(非原创)
文章大纲 一.okhttp基础介绍二.socket通讯代码实战三.项目源码下载四.参考文章 一.okhttp基础介绍 二.socket通讯代码实战 1. 添加依赖和权限 app的build.gradl ...
- Android客户端与服务器端socket通讯
Android客户端与服务器端的Socket通讯: socket通讯依赖IP地址和端口号,每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务. 服务器端代码: 实例化主类, ...
- Android模拟服务端下发消息的Socket通讯工具
Android模拟服务端下发消息的Socket通讯工具 1. 背景简介 背景简介: 有些场景需要依赖服务端下发消息到客户端,比如PowerMsg,服务端下发消息Type,客户端解析Type做出相应动作 ...
- android模拟器socket服务端,android 模拟器跟电脑服务器端用socket通讯
android 模拟器和电脑服务器端用socket通讯 之前一直会用sockets来实现emulator和PC进行通讯,卡了几天,最后请教其他人终于可以连接了. 错误原因是在IP和端口,IP要用本机 ...
- 获取android模拟器的IP地址,Android模拟器的ip获取以及模拟器之间socket通讯
一.Android 获取本机Mac 地址方法:java 须要在AndroidManifest.xml文件中添加权限:android shell Java代码服务器 public String get ...
- android socket 发送byte_如何正确地创建和销毁网络通讯程序中的Socket类的对象实例...
软件项目实训及课程设计指导--如何正确地创建和销毁软件应用系统中网络通讯中的Socket类的对象实例 1.基于TCP/IP协议的Socket通信相关的基础知识 (1)TCP/IP(Transmissi ...
- android socket第三方库,OkSocket 一个Android轻量级Socket通讯框架
OkSocket Document An blocking socket client for Java application or Andorid. Open source licenses Ba ...
最新文章
- spring boot socket长连接_springboot 整合阿里 druid 数据库连接池实战
- Tomcat Server 配置
- 《机器学习实战》chapter05 Logistic回归
- Oracle查询数据库中所有表的记录数
- Bootstrap开发框架视频整理
- Spring Cloud 中 分布式事务解决方案 -- 阿里GTS的使用
- Git:小乌龟报错no supported authentication methods avaiable
- linux版本的redis bin,redis-4.0.2.tar.gz for centos的linux系统版本下载(安装详细步骤)...
- 《Python入门到精通》文件操作
- nginx启动时报错:bind() to 0.0.0.0:80 failed
- [Java] 蓝桥杯ADV-209 算法提高 c++_ch02_04
- layer自动补全 select
- select中常用的对象
- redis的set集合
- markDown 下载安装教程
- [4G+5G专题-132]: 传输层 - 以太网电缆的类型(Cat5,Cat5e,Cat6,Cat6a)
- 计算机图形学:DDA(数值微分)画线法
- 海洋cms常见问题有哪些?
- java string newline,Java BufferedWriter newLine()用法及代码示例
- VMWARE虚拟机网络环境配置