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端

http://man7.org/linux/man-pages/man7/unix.7.html

socket的构造函数如下:

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

而unix socket的构造

#include <sys/socket.h>
#include <sys/un.h>

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

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

#include <stdio.h>  
#include <stddef.h>  
#include <sys/stat.h>  
#include <sys/socket.h>
#include <sys/un.h>  
#include <errno.h>  
#include <string.h>  
  
/* 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端

https://github.com/mcfunley/juds
https://github.com/jnr/jnr-unixsocket
https://github.com/kohlschutter/junixsocket

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
问题有待解决。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容