android socket java和C通信
来源:互联网 发布:linux自动挂载硬盘 编辑:程序博客网 时间:2024/06/06 00:01
原址
最近一直在弄一些Android跟socket相关的东西,打算好好总结一下Android socket的使用。其实Android是将进程的概念给弱化了的,但是进程还是存在的,基本上一般的app,如果你没有特殊处理的话,一个app就是一个进程。我们平时开发App的时候,更多的是基于Android基本组件概念的,也就是说Android四大组件 Activity,Service,BroadCast receiver,Content provider。但是如果需要在进程间通信,socket 是一个很不错的选择。当然,上一篇博客也讲到过管道。管道也是可以实现进程间通信的。下面主要从NDK以及java层对Android socket 相关的一些东西进行总结介绍。
我们在其他地方使用socket 一般是一个地址,一个端口。但是在Android中,建立socket 是通过一个叫做socketName 的东西。客户端和服务器端使用同一个socketName就可以建立连接。服务器端建一个指定socketName的socketserver,客户端连接到指定socketName的Socket服务器。下面介绍具体的方式。
NDK 层
android jni socket 其实就是linux socket。本身android就是基于linux 内核的。所以linux那一套东西,在android上面基本上是适用的,当然也有一些不同。
SOCKET SERVER
首先描述一下整个过程。先通过函数android_get_socket(SOCKET_NAME)来获取一个监听号。然后使用得到的监听号,以及设置的最大请求数,监听这个监听号。最后调用accept 函数等待请求。接收到数据方面的东西其实跟linux是一样的。下面看从网友提供的代码简化的具体的代码
#define SOCKET_NAME "socketnamexxx"#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>#include <sys/un.h>#include <cutils/sockets.h>#include <utils/Log.h>#include <android/log.h>int main(){ char log[200]; int connect_number = 6; int fdListen = -1, new_fd = -1; int ret; struct sockaddr_un peeraddr; socklen_t socklen = sizeof (peeraddr); int numbytes ; char buff[256]; //这一步很关键,就是获取init.rc中配置的名为 "htfsk" 的socket //fdListen = android_get_control_socket(SOCKET_NAME); //上面这个api 可能在高版本的ndk中已经不存在了。 fdListen = socket(AF_LOCAL, SOCK_STREAM, PF_UNIX); if(fdListen < 0) return (false); // set socket is reusable int option = true; if(setsockopt(fdListen, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option)) < 0) { //close(fdListen); return (false); } if(bind(fdListen, (const struct sockaddr*)& peeraddr, socklen) < 0) { close(fdListen); return (false); } if (fdListen < 0) { sprintf(log,"Failed to get socket '" SOCKET_NAME "' errno:%d", errno); __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log); exit(-1); } //开始监听 ret = listen(fdListen, connect_number); if (ret < 0) { //小于0 表示监听失 sprintf(log,"Listen result %d",ret); __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log); exit(-1); } //等待Socket客户端发启连接请求 new_fd = accept(fdListen, (struct sockaddr *) &peeraddr, &socklen); sprintf(log,"Accept_fd %d",new_fd); __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log); if (new_fd < 0 ) { sprintf(log,"%d",errno); __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log); perror("accept error"); exit(-1); } while(1){ //循环等待Socket客户端发来消息 __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI","Waiting for receive"); if((numbytes = recv(new_fd,buff,sizeof(buff),0))==-1){ sprintf(log,"%d",errno); __android_log_write(ANDROID_LOG_DEBUG,"FTM_JNI",log); perror("recv"); continue; } //发送消息回执给Socket客户端 if(send(new_fd,buff,strlen(buff),0)==-1) { perror("send"); close(new_fd); exit(0); } } close(new_fd); close(fdListen); return 0;}
其实认真跟linux的函数比较一下就会发现。这个函数android_get_socket(SOCKET_NAME) 是将端口,都整合好了。通过SocketName来指定对应的位置。弱化了原本端口和地址的概念。其他的accept,接收recv 和发送 send 其实是跟linux一样的。
SOCKET CLIENT
Client 也是依据SOCKET_NAME 来与对应的Server建立连接。具体的Demo程序如下:
char[10] socketName = "socketnamexxx"; //socketName int clientFD = 0 ;socklen_t serverLen = 0;struct sockaddr_un serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));//init socket// check socket name to avoid overflowif (strlen(socketName) > (int) sizeof(serverAddr.sun_path)) return 0;serverAddr.sun_path[0] = '\0';strcpy(serverAddr.sun_path + 1, socketName);serverAddr.sun_family = AF_LOCAL;serverLen = 1 + strlen(socketName) + offsetof(struct sockaddr_un, sun_path);if ((clientFD = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { __android_log_write(ANDROID_LOG_ERROR, LOGTAG_CCLIENT, "create socket error"); return 0;}sockaddr pserverAddr = (sockaddr) serverAddr;if (connect(&clientFD, &pserverAddr, serverLen) == -1) { //连接失败 return 0;}char[6] data="hello";if (send(clientFD, data, 6, 0) == -1) { __android_log_write(ANDROID_LOG_ERROR, LOGTAG_CCLIENT, "send message error"); close(clientFD); return 0;}
Java层
在java层的话,其实相对来说就简单了。当然指定位置的同样是SocketName。另外两个就是LocalSocket 跟LocalServerSocket了。接着就是java 通用的输入输出流了。
借用一下网友的图片来直接描述一下他们直接的关系:
在Client Socket 范例代码是:
LocalSocket socket = new LocalSocket();LocalSocketAddress address = new LocalSocketAddress(SocketName,LocalSocketAddress.Namespace.RESERVED);//第二个参数是命名空间,直接用上面那个enum 选择一个就好socket.connect(address);//socket.getInputStream(); 读取//socket.getOutputStream(); 写入
在Server Socket 如下:
LocalServerSocket server = new LocalServerSocket(SocketName);try{ LocalSocket receiver = server.accept();}catch(IOException e){ e.printStackTrace();}//读取与写入跟客户端类似,都是利用流来做的。//receiver.getInputStream(); 读取//receiver.getOutputStream(); 写入
总结
其实Socket 连接关键还是在于地址。客户端和服务器端,其实都是指定了相同的地址。服务器端监听,客户端向该地址请求。在Android socket中,它替换了直接的地址,而是用名称来标志,这样就变得更加简单。但是万变不离其宗,概念还是依据于基本的socket的。
之后再写一个demo程序。但是个人有时候觉得,demo能够让你快速了解,但是到了一定程度后,跑个程序时累赘。信手拈来才是Perfect的。
https://github.com/xxxzhi/AndroidSocketDemo
大四已经逐渐完了,在读研方面,曾对我有醍醐灌顶之效的一句话是:厚积薄发。
- android socket java和C通信
- Android java和C的Socket通信demo(可用)
- c 和 java 通过 socket 进行通信
- JAVA和C之间的socket通信
- android的NDK和java进行本地socket通信-----C服务端,java客户端
- Socket通信,Android,java
- android native c java进行本地socket通信
- android native c java进行本地socket通信
- android native c java进行本地socket通信
- java和vb进行socket通信以及java与c/c++/oc 进行socket通信时汉字字符串编码问题解决
- android socket通信java+c++
- android java socket通信乱码
- android native C 和 java 通信
- android native C 和 java 通信
- android的NDK和java进行本地socket通信
- android的NDK和java进行本地socket通信
- android的NDK和java进行本地socket通信
- android 6.0 Java层和native守护进程socket通信
- Python中的布尔类型的注意点
- linux中线程ID与进程ID
- Egyptian Fractions (HARD version) UVA
- 信息系统分析与设计----系统分析概述
- jvm什么时候会触发full gc
- android socket java和C通信
- SylixOS块设备CACHE管理
- JSCPC 2017 参赛总结
- 2004年分区联赛提高组之三 合唱队形(dp)
- 【java】线程同步关键字volatile,synchronize,取消串行化关键字transient
- 离散题目8
- oracle 通用函数
- Web Fragment在项目中的使用
- 蓝桥杯 算法训练 Hankson的趣味题(数论)