Android native进程间通信实例-socket本地通信篇之——基本通信功能
导读:
网上看了很多篇有关socket本地通信的示例,很多都是调通服务端和客户端通信功能后就没有下文了,不太实用,真正开发中遇到的问题以及程序稳定性部分没有涉及,代码健壮性不够,本系列(socket本地通信篇)会先直接调通linux本地socket通信,提供最基本的服务端和客户端代码,然后根据实际开发中遇到的问题和优化建议,再提供一版健壮版本的服务端代码。再次明确一点,本篇博文不会搬移太多概念性的东西,比如三次握手协议,还有各个unix系统调用的功能。
1.服务端:
先捋清调用的一个时间顺序,UNIX中服务端的标准API设置如下:
a. socket设置通信域等信息获取一个fd(文件描述符)
b. bind设置相关参数,如获取的fd,sockaddr_un信息等
c. listen标记fd,查看这个fd是否ok
d. accept填入fd和即将连接的客户端的sockaddr_un信息,阻塞着,直到有客户端连接,消除阻塞
(注意:以上具体API信息可以查看man手册,如listen,在ubuntu系统中输入man 2 listen即可查阅)
明确了以上信息后,就可以开始着手写代码了!代码如下:
#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 <arpa/inet.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <cutils/sockets.h>
#include <utils/Log.h>
#include <android/log.h>
#include <linux/tcp.h> #define MYSOCKET_PATH "/tmp/mysocket" void *client_thread(void *arg)
{
int clifd = *(int *)arg;char *s = "hello mysocketclient\n";
while()
{
usleep();
write(clifd,s,strlen(s));//也可以使用send(clifd,s,strlen(s),0);
} return (void *);
} int main(int argc,char **arg)
{
int servfd;
int ret; servfd = socket(AF_LOCAL,SOCK_STREAM,);
if(- == servfd)
{
perror("Can not create socket");
return -;
} struct sockaddr_un servaddr;
bzero(&servaddr, sizeof(servaddr));
strcpy(servaddr.sun_path+, MYSOCKET_PATH);
servaddr.sun_family = AF_LOCAL;
socklen_t addrlen = + strlen(MYSOCKET_PATH) + sizeof(servaddr.sun_family); ret = bind(servfd, (struct sockaddr *)&servaddr, addrlen);
if(- == ret)
{
perror("bind failed");
return -;
} ret = listen(servfd, );
if(- == ret)
{
perror("listen failed");
return -;
} int clifd = -;;
pthread_t tid;
struct sockaddr_un cliaddr;
while()
{
printf("wait for next client connect \n");
memset(&cliaddr,,sizeof(cliaddr));
clifd = accept(servfd,(struct sockaddr *)&cliaddr,&addrlen);
if(clifd == -)
{
printf("accept connect failed\n");
continue;
}
ret = pthread_create(&tid,NULL,client_thread,&clifd);
if( != ret)
{
printf("pthread_create failed \n");
} ret = pthread_join(tid, NULL);
if( != ret)
{
printf("pthread_join failed \n");
}
printf("exit thread\n");
/*
ret = pthread_detach(tid);
if(0 != ret)
{
printf("pthread_detach failed \n");
return -1;
}*/
} return ;
}
可知 #define MYSOCKET_PATH "/tmp/mysocket" 定义的字符串用于本地socket通信服务端和客户端关联。
再看看while(1)里面做了什么:
代码运行阻塞在accept这里,等着客户端的连接,如果客户端连接上以后,创建一个线程传入客户端的fd,然后在线程里面处理客户端的信息,这里创建的线程默认一直发送字符串给客户端。
线程的回收可以用到pthread_join或者pthrea_detach,然后可以等待下一个客户端连接,最大连接数在listen的时候有设置。
服务端代码还无法验证,因为客户端代码还没写好。
2.客户端:
客户端代码更好写一点,捋清顺序:
1. socket设置通信域等信息获取一个fd(文件描述符)
2. connect根据socket设置的信息来连接服务端,信息中包括那个关键字符串MYSOCKET_PATH
代码如下:
#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 <arpa/inet.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <cutils/sockets.h>
#include <utils/Log.h>
#include <android/log.h> #define SOCKET_PATH "/tmp/mysocket" int main(int argc,char **arg)
{
int clifd;
int ret; clifd = socket(AF_LOCAL, SOCK_STREAM, );
if(- == clifd)
{
perror("socket create failed\n");
return -;
} struct sockaddr_un cileddr;
bzero(&cileddr, sizeof(cileddr));
strcpy(cileddr.sun_path + , SOCKET_PATH);
cileddr.sun_family = AF_LOCAL;
socklen_t addrlen = sizeof(cileddr.sun_family) + strlen(SOCKET_PATH) + ; ret = connect(clifd, (struct sockaddr *)&cileddr, addrlen);
if(ret == -) {
perror("Connect fail\n");
return -;
} char getData[];
while()
{
bzero(&getData,sizeof(getData));
ret = read(clifd,&getData,sizeof(getData));
if(ret > )
{
printf("rcv message: %s\n", getData);
}
} return ;
}
3. 运行程序及思考
android.mk的编写和之前一样,只需要更改cpp文件名以及LOCAL_MODULE名,传送门:https://www.cnblogs.com/songsongman/p/11097196.html
编写完后编译,把两个可执行文件导入设备中,先执行服务端,然后再执行客户端,发现通信正常,服务端发送,客户端接收,似乎完美?

但是当客户端强行退出后,服务端进程居然退出了!!!怎么办,且听下篇分解。
Android native进程间通信实例-socket本地通信篇之——基本通信功能的更多相关文章
- Android native进程间通信实例-socket本地通信篇之——服务端进程异常退出解决办法
导读: 好难受啊,为什么服务端说挂就挂,明明只是客户端关闭而已,服务端怎么能挂呢? 想想,如果手机上使用一个聊天程序的时候,手机端关闭了聊天程序,那么远端服务器程序总不能说挂就挂吧!所以一定要查明真相 ...
- Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务
有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...
- Android native进程间通信实例-binder篇之——简单的单工通信
网上找了很多binder相关文章,大部分都是在跟踪binder实现源代码,然后再把框架代码贴出来,看着实在费力. 这篇文章从实际出发,直接用一个案例下手,后续想了解binder相关原理的话,可以参考& ...
- Android native进程间通信实例-binder篇之——用parcel传输数组
和之前稍微不同,这次要稍微分析一下 Parce.cpp 和 android_os_Parcel.cp p的源码,为的是能够掌握调试技巧,后续传输其它类型数据就能举一反三了! 1. 代码共享 这次 ...
- Android native进程间通信实例-binder篇之——解决实际问题inputreader内建类清楚缓存
我在实际开发中,遇到一个问题,在电容屏驱动中没有发送input_sync 给上层,导致电容屏有的数据缓存在inputreader 中,会导致系统一系列奇怪问题发生, 至于为什么驱动不发送input_s ...
- Android native进程间通信实例-binder结合共享内存
在android源码的驱动目录下,一般会有共享内存的相关实现源码,目录是:kernel\drivers\staging\android\ashmem.c.但是本篇文章不是讲解android共享内存的功 ...
- Android进程间通信之socket通信
用Java中的socket编程. 通过socket实现两个应用之间的通信,可以接收和发送数据,同时将接收到的数据显示在activity界面上. Server端: ServerLastly.java p ...
- 通信(二):进程间通信之socket
一.为什么要学习socket? 我们打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?我们用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket.本地的进程间通 ...
- Android Native -- Message/Handler/Looper机制(原理篇)
⌈Android Native消息队列处理系列文章⌋ Android Native -- Message/Handler/Looper机制(原理篇) Android Native -- Message ...
随机推荐
- 【Ubuntu】查看进程端口占用信息
1.查看进程信息 ①进程查看 ps -aux ②根据PID查看进程 ps -aux | grep pid ③进程计数,查看指定进程 ps -aux | wc -l ps -aux | grep kwo ...
- Win8 Metro(C#)数字图像处理--2.58双峰法图像二值化
原文:Win8 Metro(C#)数字图像处理--2.58双峰法图像二值化 [函数名称] 双峰法图像二值化 WriteableBitmap PeakshistogramThSegment( ...
- 利用NPOI生成DOCX文档
首先安装NPOI控件: Install-Package NPOI 代码: using NPOI.OpenXmlFormats.Wordprocessing; using NPOI.XWPF.UserM ...
- Java Web系列:Spring Boot 基础 Spring Security基本使用
@OneToOne or @ManyToOne Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com ...
- 我怎么忽略了身份框架魔法,只是使用OWIN验证的中间件,以获得要求我寻求什么呢?
该OWIN中间件的东西第三方登录集成到您的ASP.NET应用程序是非常酷的,但我似乎无法弄清楚如何就剜出来的新的ID,它取代了蹩脚的成员身份 API.我没有兴趣在坚持所产生的债权,并在英法为基础的数据 ...
- 剖析Qt的事件机制原理(源代码级别)
在用Qt写Gui程序的时候,在main函数里面最后依据都是app.exec();很多书上对这句的解释是,使Qt程序进入消息循环.下面我们就到exec()函数内部,来看一下他的实现原理.Let's go ...
- ab fails to connect to localhost
The following command fails: $ ab -n 1 localhost:8000/ ... Benchmarking localhost (be patient)...apr ...
- is和==的区别以及编码和解码
一.is和==的区别 python中对象包含的三个基本要素分别是:id(身份标识),type(数据类型),value(值) is和==都是对对象进行比较判断的,但对对象比较判断的内容不同. ★==是p ...
- 平衡二叉树 JAVA实现 亲测可用
平衡二叉树的JAVA实现 亲测可用 包括LL LR RL RR四种情况的旋转算法 以及添加删除树结点之后对平衡二叉树的维护算法 都已经实现并测试过 没有问题. 代码地址可以直接上我的GIT clone ...
- vmware centos7虚拟机克隆系统如何修改网卡设置?
1.克隆虚拟机,克隆前需关闭虚拟机2.克隆之后的网卡问题解决,其中需要修改HWADDR和UUID /etc/sysconfig/network-scripts/ifcfg-ens32 uuid获取 ...