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 ...
随机推荐
- 开源数据源使用 DBCP 和 C3PO
jar包: commons-dbcp-1.4.jar commons-pool-1.5.6.jar mysql-connector-java-5.0.8-bin.jar 建立dbcp的配置文件 dbc ...
- 查看安卓APK源码破解
原文:查看安卓APK源码破解 工具准备: <1>.android4me的AXMLPrinter2工具 <2>dex2jar <3>jd-gui 工具下载:http: ...
- 【shell】分享高通平台刷版本简单的一个shell脚本
#!/bin/shadb wait-for-deviceadb reboot bootloaderecho "start download"wait 5sudo fastboot ...
- Win10《芒果TV》送7天免费会员,邀您抢先看萌心自制《妈妈是超人3》
<妈妈是超人>第三季萌心归来,霍思燕,贾静雯,黄圣依,邓莎联合释放"妈妈的声音",嗯哼,咘咘,波妞,安迪,大麟子五位萌娃共同出镜,萌化屏幕.Win10<芒果TV& ...
- Android零基础入门第24节:自定义View简单使用
原文:Android零基础入门第24节:自定义View简单使用 当我们开发中遇到Android原生的组件无法满足需求时,这时候就应该自定义View来满足这些特殊的组件需求. 一.概述 很多初入Andr ...
- 企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(2)
本书包含的章节内容 第一章:表现模式,以一个例子呈献给读者表现模式的发展历程,我们会用包括MVC和MVP在内的各种方式实现一个收费项目的例子.沿此方向,我们会发现每一种模式的问题所在,这也是触发设计模 ...
- OpenSSL的命令行用法,以及参数大全
c:\openssl\bin>opensslOpenSSL> versionOpenSSL 1.0.2j 26 Sep 2016OpenSSL> https://wiki.opens ...
- 2016最受欢迎国产开源软件评选,2016 年度开源中国新增开源软件排行榜 TOP 100
http://www.oschina.net/news/80154/2016-cn-open-source-software-top http://www.oschina.net/project/to ...
- Tinyhttpd for Windows(500多行)
TinyHTTPd forWindows 前言 TinyHTTPd是一个开源的简易学习型的HTTP服务器,项目主页在:http://tinyhttpd.sourceforge.NET/,源代码下载:h ...
- 07 jQuery的位置信息
一.宽度和高度 获取宽度 .width() 描述:为匹配的元素集合中获取第一个元素的当前计算宽度值.这个方法不接受任何参数..css(width) 和 .width()之间的区别是后者返回一个没有单位 ...