android jni socket

其实这个标题没什么意思;但是想来想去,自己(新手)查了很多资料才调通,就打算在此一写。

        android-jni的socket编程,就是调用底层linux的socket编程。android平台,一般只需要关心客户端代码,如下:(从华清远见嵌入式linux应用开发教材上copy的,手头没好点的例子)

  1. /*client.c*/  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <errno.h>  
  5. #include <string.h>  
  6. #include <netdb.h>  
  7. #include <sys/types.h>  
  8. #include <netinet/in.h>  
  9. #include <sys/socket.h>  
  10. #define SERVPORT 8591  
  11. #define MAXDATASIZE 100  
  12. main(int argc,char *argv[])  
  13. {  
  14.     int sockfd,sendbytes;  
  15.     char buf[MAXDATASIZE];  
  16.     struct hostent *host;  
  17.     struct sockaddr_in serv_addr;  
  18.     if (argc < 2)  
  19.     {  
  20.         fprintf(stderr,"Please enter the server's hostname! ");  
  21.         exit(1);  
  22.     }  
  23.     /*地址解析函数*/  
  24.     if ((host=gethostbyname(argv[1]))==NULL)  
  25.     {  
  26.         perror("gethostbyname");  
  27.         exit(1);  
  28.     }  
  29.     printf("%s",host->h_name);  
  30.     /*创建socket*/  
  31.     if ((sockfd=socket(AF_INET,SOCK_STREAM,0))== -1)  
  32.     {  
  33.         perror("socket");  
  34.         exit(1);  
  35.     }  
  36.     /*设置sockaddr_in 结构体中相关参数*/  
  37.     serv_addr.sin_family=AF_INET;  
  38.     serv_addr.sin_port=htons(SERVPORT);  
  39.     serv_addr.sin_addr=*((struct in_addr *)host->h_addr);  
  40.     bzero(&(serv_addr.sin_zero),8);  
  41.     /*调用connect函数主动发起对服务器端的连接*/  
  42.     if (connect(sockfd,(struct sockaddr *)&serv_addr,  
  43.                 sizeof(struct sockaddr))== -1)  
  44.     {  
  45.         perror("connect");  
  46.         exit(1);  
  47.     }  
  48.     /*发送消息给服务器端*/  
  49.     if ((sendbytes=send(sockfd,"hello",5,0))== -1)  
  50.     {  
  51.         perror("send");  
  52.         exit(1);  
  53.     }  
  54.     close(sockfd);  
  55. }  

然后可以参照android-ndk的sample把它改成jni方式调用。


        接收消息,可以采用如下方式:(参考APUE)

  1. long  ReceiveMessage(BYTE *buf,UINT bufSize,UINT *recvbufLen,UINT nTimeOut)  
  2. {  
  3.     LOGI("ReceiveMessage");  
  4.   
  5.     long lRet = -1;  
  6.   
  7.     int recvbytes;  
  8.     uint startTime = GetTickCount(),endTime;  
  9.     do  
  10.     {  
  11.         endTime = GetTickCount();  
  12.         if ((recvbytes=recv(sockfd, buf, bufSize, MSG_DONTWAIT)) == -1)  
  13.         {  
  14.             lRet = -1;  
  15.             //LOGI("recv error");  
  16.             //LOGII(errno,"recv errno",__LINE__); // 11 : Resource temporarily unavailable  
  17.         }  
  18.         else  
  19.         {  
  20.             lRet = 0;  
  21.             break;  
  22.         }  
  23.     }while(lRet == -1 && endTime - startTime < nTimeOut);  
  24.   
  25.     *recvbufLen = recvbytes;  
  26.     if(recvbytes > 0)  
  27.         LOGArr((unsigned char*)buf,recvbytes);  
  28.   
  29.     return lRet;  
  30. }  


        上例中用指针传输出参数而不是引用,是因为是在.c文件中编译jni,不支持c++特性。而jni-c++这一部分还没完全搞清楚,等搞清楚了再写一篇。

     

        需要说明的最重要的一点是,工程目录下的AndroidManifest.xml需要添加网络权限支持才能调通:

  1. <!-- 增加jni socket支持-->  
  2.     <uses-permission android:name="android.permission.INTERNET" />   
原文地址:https://www.cnblogs.com/hzcya1995/p/13318675.html