导读:

  网上看了很多篇有关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本地通信篇之——基本通信功能的更多相关文章

  1. Android native进程间通信实例-socket本地通信篇之——服务端进程异常退出解决办法

    导读: 好难受啊,为什么服务端说挂就挂,明明只是客户端关闭而已,服务端怎么能挂呢? 想想,如果手机上使用一个聊天程序的时候,手机端关闭了聊天程序,那么远端服务器程序总不能说挂就挂吧!所以一定要查明真相 ...

  2. Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

    有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...

  3. Android native进程间通信实例-binder篇之——简单的单工通信

    网上找了很多binder相关文章,大部分都是在跟踪binder实现源代码,然后再把框架代码贴出来,看着实在费力. 这篇文章从实际出发,直接用一个案例下手,后续想了解binder相关原理的话,可以参考& ...

  4. Android native进程间通信实例-binder篇之——用parcel传输数组

     和之前稍微不同,这次要稍微分析一下 Parce.cpp 和 android_os_Parcel.cp p的源码,为的是能够掌握调试技巧,后续传输其它类型数据就能举一反三了!   1. 代码共享 这次 ...

  5. Android native进程间通信实例-binder篇之——解决实际问题inputreader内建类清楚缓存

    我在实际开发中,遇到一个问题,在电容屏驱动中没有发送input_sync 给上层,导致电容屏有的数据缓存在inputreader 中,会导致系统一系列奇怪问题发生, 至于为什么驱动不发送input_s ...

  6. Android native进程间通信实例-binder结合共享内存

    在android源码的驱动目录下,一般会有共享内存的相关实现源码,目录是:kernel\drivers\staging\android\ashmem.c.但是本篇文章不是讲解android共享内存的功 ...

  7. Android进程间通信之socket通信

    用Java中的socket编程. 通过socket实现两个应用之间的通信,可以接收和发送数据,同时将接收到的数据显示在activity界面上. Server端: ServerLastly.java p ...

  8. 通信(二):进程间通信之socket

    一.为什么要学习socket? 我们打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?我们用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket.本地的进程间通 ...

  9. Android Native -- Message/Handler/Looper机制(原理篇)

    ⌈Android Native消息队列处理系列文章⌋ Android Native -- Message/Handler/Looper机制(原理篇) Android Native -- Message ...

随机推荐

  1. WPF关于控件 父级控件,子级控件,控件模板中的控件,等之间的相互访问

    原文:WPF关于控件 父级控件,子级控件,控件模板中的控件,等之间的相互访问 1,在菜单中访问 弹出菜单的控件 var mi = sender as MenuItem;//菜单条目 MenuItem ...

  2. 【全面解禁!真正的Expression Blend实战开发技巧】第五章 从最常用ButtonStyle开始 - ImageButton

    原文:[全面解禁!真正的Expression Blend实战开发技巧]第五章 从最常用ButtonStyle开始 - ImageButton 本章围绕ImageButton深入讨论,为什么是Image ...

  3. Python编写AWS Version 4 signing (AWS4-HMAC-SHA256) for execute-api

    官网教程中给了签署AWS请求给了详细的介绍和python的例子,但是例子针对DynamoDB API,本例子针对API Gateway的POST请求,并携带有x-amz-security-token. ...

  4. 通过异步程序调用(APC)实现的定时功能

    定时器是一个在特定时间或者规则间隔被激发的内核对象.结合定时器的异步程序调用可以允许回调函数在任何定时器被激发的时候执行.本文的例子代码显示了如何实现. 使用本定时器时,你需要把常量_WIN32_WI ...

  5. CopyFile函數詳解

    CopyFile函數,文件拷贝函数.其基本結構如下: copyfile( lpcstr lpexistingfilename, // 源文件路径 lpcstr lpnewfilename, //新文件 ...

  6. WIFI Manager

    Vistumbler - wifi managerhttps://www.vistumbler.net/downloads.htmlhttps://github.com/RIEI

  7. Window Features(包括Z-Order,Layered Windows, Message-Only Windows, Owned Windows, Window的状态等)

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms632599(v=vs.85).aspx#owned_windows https: ...

  8. hive Metastore contains multiple versions

    凌晨接到hive作业异常,hive版本为1.2.1,hadoop版本apache 2.7.1,元数据存储在mysql中,异常信息如下: Logging initialized using config ...

  9. Python 爬虫从入门到进阶之路(七)

    在之前的文章中我们一直用到的库是 urllib.request,该库已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Hum ...

  10. 系统学习 Java IO (五)----使用 SequenceInputStream 组合多个流

    目录:系统学习 Java IO---- 目录,概览 SequenceInputStream 可以将两个或多个其他 InputStream 合并为一个. 首先,SequenceInputStream 将 ...