参考:树莓派与安卓手机app的WIFI通信(局域网通信)
作者:图触靓
发布时间: 2020-07-29 10:18:12
网址:https://blog.csdn.net/bhbhhyg/article/details/107655967

树莓派作为服务器

与树莓派与wemos的无线通信类似,只不过这次我们将客户端变为安卓手机,树莓派作为服务器。

#include <sys/types.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include<string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int initsocket(){
        int s_fd=socket(AF_INET, SOCK_STREAM,0);
        if (s_fd==-1)
        {
                perror("socket");
                exit(-1);
        }
        struct sockaddr_in addr;
        memset(&addr,0,sizeof(struct sockaddr_in));
 
        addr.sin_family=AF_INET;
        addr.sin_port=htons(9001); //端口号
        inet_aton("192.168.200.XXX",&addr.sin_addr);//IP地址
        //        addr.sin_port=htons(atoi(argv[2]));
        //       inet_aton(argv[1],&addr.sin_addr);
        int bid=bind(s_fd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in));
        listen(s_fd,10);
        int len=sizeof(struct sockaddr_in);
        return s_fd;
}
 
int main(){
        char readbuf[2]={0};
        int s_fd=initsocket();  //初始化服务器
 
        printf("wait connect.....\n");
        while(1){
                int fd_a=accept(s_fd,NULL,NULL); //该函数用来接受连接,没有连接的时候也可以用来阻塞while(1)
                printf("connect\n");
                memset(readbuf,0,2);           //初始化字符串
                int r=read(fd_a,readbuf,2);   //读指令
                if(r==-1)
                {
                        perror("read");
                }
                else
                {
 
                       printf("  cmd is %c \n",readbuf[0]);//打印安卓客户端发来的指令
 
                }

安卓端连接服务器的方法

package com.example.smarthome;
 
 
import java.io.OutputStream;
import java.net.Socket;
 
import android.os.Handler;
 
 
 
public class NetUtils {
 
	public String message;
	public String reTurnMes;
	public Handler handler;
 
	public NetUtils(String message) {
		this.message = message;
	}
 
	public NetUtils(String message, Handler handler) {
		this.message = message;
		this.handler = handler;
	}
 
	public void sendMessage() {
 
		new Thread(new Runnable() {
 
			@Override
			public void run() {
			
				try {
					Socket client = new Socket("192.168.XXX.XXX",9001);//与服务器对应的IP地址与端口号
					OutputStream out = client.getOutputStream(); 
					out.write(message.getBytes());  //像服务器发送信息
					
					out.close();    //关闭输入流
					client.close();  //客户端的连接
					
 
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
 
	}
}

安卓AndroidManifest中需要添加的权限:

     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />

安卓按键发送的写法

Button kd=(Button)findViewById(R.id.kd);
kd.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
			  new NetUtils("A").sendMessage();
			}
		});

最后,需要注意的是,安卓给服务器发送数据是按键一次,建立一个线程并连接一次莓派端服务器,发送完成再断开。所以我们需要将树莓派端的服务器阻塞设置为连接,而不是一次连接后,不断的循环读客户端的数据,否则当客户端发完数据后,断开连接,服务器还一直在循环的读上一个连接的数据,造成死循环。

所以服务器正确的设置应该为,接受一次连接,读一次,阻塞等待下一次的连接。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐