本文由 @lonelyrains 出品,转载请注明出处。
文章链接: http://blog.csdn.net/lonelyrains/article/details/8313755
android-jni的socket编程,就是调用底层linux的socket编程。android平台,一般只需要关心客户端代码,如下:(从华清远见嵌入式linux应用开发教材上copy的,手头没好点的例子)
/*client.c*/ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define SERVPORT 8591 #define MAXDATASIZE 100 main(int argc,char *argv[]) { int sockfd,sendbytes; char buf[MAXDATASIZE]; struct hostent *host; struct sockaddr_in serv_addr; if (argc < 2) { fprintf(stderr,"Please enter the server's hostname!\n"); exit(1); } /*地址解析函数*/ if ((host=gethostbyname(argv[1]))==NULL) { perror("gethostbyname"); exit(1); } printf("%s",host->h_name); /*创建socket*/ if ((sockfd=socket(AF_INET,SOCK_STREAM,0))== -1) { perror("socket"); exit(1); } /*设置sockaddr_in 结构体中相关参数*/ serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(SERVPORT); serv_addr.sin_addr=*((struct in_addr *)host->h_addr); bzero(&(serv_addr.sin_zero),8); /*调用connect函数主动发起对服务器端的连接*/ if (connect(sockfd,(struct sockaddr *)&serv_addr,\ sizeof(struct sockaddr))== -1) { perror("connect"); exit(1); } /*发送消息给服务器端*/ if ((sendbytes=send(sockfd,"hello",5,0))== -1) { perror("send"); exit(1); } close(sockfd); }
然后可以参照android-ndk的sample把它改成jni方式调用。
接收消息,可以采用如下方式:(参考APUE)
long ReceiveMessage(BYTE *buf,UINT bufSize,UINT *recvbufLen,UINT nTimeOut) { LOGI("ReceiveMessage"); long lRet = -1; int recvbytes; uint startTime = GetTickCount(),endTime; do { endTime = GetTickCount(); if ((recvbytes=recv(sockfd, buf, bufSize, MSG_DONTWAIT)) == -1) { lRet = -1; //LOGI("recv error"); //LOGII(errno,"recv errno",__LINE__); // 11 : Resource temporarily unavailable } else { lRet = 0; break; } }while(lRet == -1 && endTime - startTime < nTimeOut); *recvbufLen = recvbytes; if(recvbytes > 0) LOGArr((unsigned char*)buf,recvbytes); return lRet; }
上例中用指针传输出参数而不是引用,是因为是在.c文件中编译jni,不支持c++特性。而jni-c++这一部分还没完全搞清楚,等搞清楚了再写一篇。
需要说明的最重要的一点是,工程目录下的AndroidManifest.xml需要添加网络权限支持才能调通:
<!-- 增加jni socket支持--> <uses-permission android:name="android.permission.INTERNET" />