最近在做android native socket通信。主要在native这里写socket服务端的程序。根据client需求,通过PC端串口发送AT command,native负责接受从PC端发送的命令,过滤有效命令,通过socket发送到APP端,APP收到命令后进行相关测试,之后将测试信息返回native,native发送到PC端串口,显示测试结果。
native的socket服务端的实现原理:创建后台服务,开启一个进程,监听串口消息。
流程如下:
1.在init.rc里增加服务
chown system system /dev/ttyGS0
chmod 0666 /dev/ttyGS0
on property:ro.baseband="unknown"
start at
service at /system/bin/at
socket sockettest stream 0666 radio system
user system
group system inet
disabled
2.native服务程序 /system/at/at.c
#if 1
#define LOG_TAG "AT"
#define SOCKET_NAME "sockettest"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFSIZE 100
int count = 0;
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "myserver", __VA_ARGS__)
int main(){
#if 1
int connect_number = 4;
int fdListen = -1, new_fd = -1;
int fd, ret;
char ttyBuf[BUFSIZE];
char *msg = "";// "ttyGS0 test";
char *end = "\r\n";
struct sockaddr peeraddr;
socklen_t socklen = sizeof (peeraddr);
int numbytes ;
char buff[256];
fd_set fds;
int max = 0;
while(1){
fd = open("/dev/ttyGS0", O_RDWR);//打开usb serial device
//printf("envi serial test program\n");
LOGD("envi serial test program","myserver");
if(fd < 0)
{
//printf("\n");
LOGD("Error: open /dev/ttyGS0 error!","myserver");
return 1;
}
fdListen = android_get_control_socket(SOCKET_NAME);//创建native socket服务端本地连接
if (fdListen < 0) {
LOGD("Failed to get socket","myserver");
exit(-1);
}
LOGD("get","myserver");
ret = listen(fdListen, connect_number); //listen
if (ret < 0) {
LOGD("listen socket failed","myserver");
//perror("listen");
//exit(-1);
}
LOGD("geta","myserver");
//It block until client connected.accept(socket_id, &peeraddr, &socklen);
#if 1
new_fd = accept(fdListen, &peeraddr, &socklen); //与client端连接
if (new_fd < 0 ) {
//LOGD("Error on accept() errno:%d", errno);
LOGD("Error on accept()","myserver");
//perror("accept");
//exit(-1);
continue;
}
LOGD("getb","myserver");
//send at command from ttyGS0
while(1){
//read from ttyGS0
memset(ttyBuf, 0, sizeof(ttyBuf));
ret = read(fd, ttyBuf, BUFSIZE);
if(ret < 0)
{
//printf("Error: read device error!\n");
//return 1;
LOGD("Error: read device error","myserver",errno);
}
if(ttyBuf[0] != NULL){
LOGD("while count","myserver",ttyBuf[0]);
LOGD("myserver","yzy is " + ttyBuf[0]);
//strcat(ttyBuf, end);//add /r/n
if(send(new_fd, ttyBuf, strlen(ttyBuf), 0) < 0) {
LOGE("send failed");
}
LOGD("get1","myserver");
#if 1
FD_ZERO(&fds);
FD_SET(new_fd, &fds);
if(new_fd > max)
max = new_fd;
if(select(max + 1, &fds, NULL, NULL, NULL) < 0)//t进行读操作
{
LOGE("select() failed","myserver");
}
if(FD_ISSET(new_fd, &fds)){
if((numbytes = recv(new_fd,buff,sizeof(buff),0))==-1)
{
LOGE("recv failed","myserver");
//perror("recv");
//exit(-1);
}
}
#endif
LOGD("get2","myserver");
if(numbytes > 0){
ret = write(fd, buff, strlen(buff));
if(ret < 0)
{
LOGD("write ttyGS0 error","myserver");
//return 1;
}
}
#endif
}
close(fd);
close(new_fd);
close(fdListen);
#endif
}
return 0;
}
#endif
3.APP端用localSocket来创建client端,用connect()函数来连接native socket server端。
LocalSocket ls = null;
LocalSocketAddress lsa;
ls = new LocalSocket();
lsa = new LocalSocketAddress(SOCKET_NAME,LocalSocketAddress.Namespace.RESERVED);//这里的SOCKET_NAME必须与native和init.rc相同,为sockettest
ls.connect(lsa);
如果socket连上没有问题,就可以收发消息了。
4.小结:native和framework的通信是通过jni,一般情况下是framework调用jni的。如果native有消息,怎么样让framework知道呢?上面使用socket通信,可以让framework和native相互通信。