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 ...
随机推荐
- C# WebRequest WebResponse的使用
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化)
原文:WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化) 注释直接写在代码里了 不太理解意思的 可以先去看看我上一篇 WPF ScrollViewer(滚动条) 自定 ...
- box-shadow 与 filter:drop-shadow 详解及技巧
box-shadow 在前端的 CSS 编写工作想必十分常见.但是 box-shadow 除去它的常规用法,其实还存在许多不为人知的奇技淫巧. 喜欢 markdown 版本的可以戳这里. box-sh ...
- Vue-cli入门(一)——项目搭建
Vue-cli入门(一)——项目搭建 前言: Vue-cli是一款基于vue的项目脚手架工具,其集成了webpack环境和主要的依赖,对于我们的项目搭建.开发.打包.维护管理等都是非常的方便. 主要内 ...
- Go 的文件系统抽象 Afero
Afero 是一个文件系统框架,提供一个简单.统一和通用的 API 和任何文件系统进行交互,作为抽象层还提供了界面.类型和方法.Afero 的界面十分简洁,设计简单,舍弃了不必要的构造函数和初始化方法 ...
- WPF之MahApps.Metro下载和WPF学习经验
这几天一直在学习WPF的东西.刚开始以为和Winform一样.拖拽控件来进行布局.结果远远没有那么简单.很多东西都需要自己写.包括样式.今天给大家分享一个 MahApps.Metro. 首先在NuGe ...
- Win8Metro(C#)数字图像处理--2.31灰度拉伸算法
原文:Win8Metro(C#)数字图像处理--2.31灰度拉伸算法 [函数名称] 灰度拉伸函数GrayStretchProcess(WriteableBitmap src) [算法说明] ...
- win10 uwp ApplicationView
原文:win10 uwp ApplicationView 本文和大家介绍一个重要的类,他可以用来设置窗口,如设置启动大小,设置是否允许截图,是否进入全屏,所有和窗口有关的,都可以在他这里设置. 可以使 ...
- 访问类的私有属性(RTTI和模仿类2种方法)
如何访问类的私有属性? 下面以 TPathData 为例,它有一个私有属性 PathData,储存了每一个曲线点,但一般无法修改它,需要利用下面方法,才能访问修改(若有更好的方法,歡迎分享): 一.利 ...
- 数据备份服务商Rubrik获4000万美元B轮融资
搜狐科技 文/丽丽卡 5月27日,数据备份服务商Rubrik获Greylock Partners领投的4000万美元B轮融资,Lightspeed Venture Partners及其现有投资者跟投, ...