android unix socket,unix socket实现进程通信

2017-5-10

需求:

arm与stm32在android平台中通信,串口由stm操作,由arm发送指令给stm,并接受stm的数据。

为什么要使用UnixDomainSocket:

Unix Socket是一种Socket方式实现进程间通信(IPC)的功能,与普通的网络socket相比,不需要进行复杂的数据打包拆包,校验和计算验证,不需要走网络协议栈,而且安全可靠(官方说明)。

方法:

socket的其中一种AF_UNIX或AF_LOCAL的类型,成为unix domain socket,是为了进行本地通信,也就是为了实现IPC,所以构造函数不需要IP和端口,取而代之的是文件路径。

c端

socket的构造函数如下:

int socket(int domain, int type, int protocol);

而unix socket的构造

#include

#include

unix_socket = socket(AF_UNIX, type, 0);

error = socketpair(AF_UNIX, type, 0, int *sv);

抄一段使用unix socket client的c代码

#include

#include

#include

#include

#include

#include

#include

/* Create a client endpoint and connect to a server. Returns fd if all OK, <0 on error. */

int unix_socket_conn(const char *servername)

{

int fd;

if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) /* create a UNIX domain stream socket */

{

return(-1);

}

int len, rval;

struct sockaddr_un un;

memset(&un, 0, sizeof(un)); /* fill socket address structure with our address */

un.sun_family = AF_UNIX;

sprintf(un.sun_path, "scktmp%05d", getpid());

len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);

unlink(un.sun_path); /* in case it already exists */

if (bind(fd, (struct sockaddr *)&un, len) < 0)

{

rval= -2;

}

else

{

/* fill socket address structure with server's address */

memset(&un, 0, sizeof(un));

un.sun_family = AF_UNIX;

strcpy(un.sun_path, servername);

len = offsetof(struct sockaddr_un, sun_path) + strlen(servername);

if (connect(fd, (struct sockaddr *)&un, len) < 0)

{

rval= -4;

}

else

{

return (fd);

}

}

int err;

err = errno;

close(fd);

errno = err;

return rval;

}

void unix_socket_close(int fd)

{

close(fd);

}

int main(void)

{

srand((int)time(0));

int connfd;

connfd = unix_socket_conn("foo.sock");

if(connfd<0)

{

printf("Error[%d] when connecting...",errno);

return 0;

}

printf("Begin to recv/send...\n");

int i,n,size;

char rvbuf[4096];

for(i=0;i<10;i++)

{

/*

//=========接收=====================

size = recv(connfd, rvbuf, 800, 0); //MSG_DONTWAIT

if(size>=0)

{

printf("Recieved Data[%d]:%c...%c\n",size,rvbuf[0],rvbuf[size-1]);

}

if(size==-1)

{

printf("Error[%d] when recieving Data.\n",errno);

break;

}

if(size < 800) break;

*/

//=========发送======================

memset(rvbuf,'a',2048);

rvbuf[2047]='b';

size = send(connfd, rvbuf, 2048, 0);

if(size>=0)

{

printf("Data[%d] Sended:%c.\n",size,rvbuf[0]);

}

if(size==-1)

{

printf("Error[%d] when Sending Data:%s.\n",errno,strerror(errno));

break;

}

sleep(1);

}

unix_socket_close(connfd);

printf("Client exited.\n");

}

要运行在Android平台上的话,要生成可执行文件,下了cygwin和mingw都没搞定。查了查发现ndk完全可以解决:就只需要在Android.mk最后的BUILD模式改成BUILD_EXECUTABLE就好,生成so文件的话模式是BUILD_SHARED_LIBRARY。

touch一个foo.sock文件,然后先运行Server端,再运行Client则可以发送成功!

java端

java需要使用第三方库才能使用unix socket,这里我们使用的是第一个mcfunley/juds,因为它star竟高出第二名15个!!!嗯。

unix socket分两种类型,一种类似TCP,叫做STREAM类型,一种类似UDP,叫做DGRAM类型。按自己的理解调用一下:

try {

boolean result = new File("/mnt/sdcard/uds").createNewFile();

Log.d(TAG, "create file result=" + result);

final UnixDomainSocketClient streamClient = new UnixDomainSocketClient("/mnt/sdcard/uds", JUDS.SOCK_STREAM);

final UnixDomainSocketServer streamServer = new UnixDomainSocketServer("/mnt/sdcard/uds", JUDS.SOCK_STREAM);

new Thread(){

@Override

public void run() {

byte[] buf = new byte[128];

try {

int count = streamServer.getInputStream().read(buf);

Log.d(TAG, "size of data=" + count);

for(byte b : buf){

Log.d(TAG, "byte=" + b);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}.start();

new Thread(){

@Override

public void run() {

try {

streamClient.getOutputStream().write("Hello stm".getBytes());

} catch (IOException e) {

e.printStackTrace();

}

}

}.start();

} catch (IOException e) {

e.printStackTrace();

}

2017-5-19

java端与c端的通信报出java.io.IOException: Unable to write to Unix domain socket

问题有待解决。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值