树莓派与Android客户端进行socket通信

2023-05-16

    首先,需要对树莓派进行配置,使其成为AP热点,这里我用的树莓派3B自带wifi蓝牙模块,树莓派3B作AP热点的方法具体参考https://blog.csdn.net/u014271612/article/details/53766627这篇文章,但配置过程中会遇到一些小问题,比如在输入 git clone https: //github.com/oblique/create_ap  这条命令时会提示需要帐号密码,而我的做法是直接上github将这个项目的zip压缩文件下载下来拷贝到我的树莓派中,然后再进行下面操作,后面还有一个问题 ,在 sudo create_ap wlan0eth0 热点名 密码 这行密码中wlan0eth0 应该在中间加一个空格,即 sudo create_ap wlan0 eth0 热点名 密码 至此树莓派作为AP热点配置成功。
    下面进入主题,树莓派与android客户端之间的通信我采用socket来实现,树莓派上我写了一个python脚本作为服务器,android作为客户端

    首先,上一下效果图:

    Android客户端:



树莓派服务器端:


    树莓派上的python脚本如下:

import socket
import time
import sys

HOST_IP = "192.168.12.1"    #我的树莓派作为AP热点的ip地址
HOST_PORT = 7654            #端口号

print("Starting socket: TCP...")
socket_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    #创建socket

print("TCP server listen @ %s:%d!" %(HOST_IP, HOST_PORT) )
host_addr = (HOST_IP, HOST_PORT)
socket_tcp.bind(host_addr)    #绑定我的树莓派的ip地址和端口号
socket_tcp.listen(1)	#listen函数的参数是监听客户端的个数,这里只监听一个,即只允许与一个客户端创建连接

while True:
	print ('waiting for connection...')
	socket_con, (client_ip, client_port) = socket_tcp.accept()    #接收客户端的请求
	print("Connection accepted from %s." %client_ip)

	socket_con.send("Welcome to RPi TCP server!")    #发送数据

	while True:
		data=socket_con.recv(1024)    #接收数据
		
		if data:    #如果数据不为空,则打印数据,并将数据转发给客户端
			print(data)
			socket_con.send(data)

socket_tcp.close()

注:上述代码注释是后期加上去的,可以将代码中的注释去掉再运行。

    接下来是Android客户端代码:

    1、XML布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="lh.wifidemo.ui.activity.Device_Control_Activity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="设备控制"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/et_send"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送"
        android:id="@+id/bt_send"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="接收到的信息:"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tv_recv"/>
</LinearLayout>

    2、Activity.java

package lh.wifidemo.ui.activity;

import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

import lh.wifidemo.R;

public class Device_Control_Activity extends ActionBarActivity {

    private EditText et_send;
    private Button bt_send;
    private TextView tv_recv;

    private String send_buff=null;
    private String recv_buff=null;

    private Handler handler = null;

    Socket socket = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_device__control_);

        initView();

        handler = new Handler();

          //单开一个线程来进行socket通信
          new Thread(new Runnable() {
              @Override
              public void run() {
                  try {
                        socket = new Socket("192.168.12.1" , 7654);
                        if (socket!=null) {
                            System.out.println("###################");
                            while (true) {      //循环进行收发
                                recv();
                                send();
                            }
                        }
                       else
                            System.out.println("socket is null");
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }).start();
        send();
    }


    private void recv() {

        //单开一个线程循环接收来自服务器端的消息
        InputStream inputStream = null;
        try {
            inputStream = socket.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (inputStream!=null){
            try {
                byte[] buffer = new byte[1024];
                int count = inputStream.read(buffer);//count是传输的字节数
                recv_buff = new String(buffer);//socket通信传输的是byte类型,需要转为String类型
                System.out.println(recv_buff);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //将受到的数据显示在TextView上
        if (recv_buff!=null){
            handler.post(runnableUi);

        }
    }

    //不能在子线程中刷新UI,应为textView是主线程建立的
    Runnable runnableUi = new Runnable() {
        @Override
        public void run() {
            tv_recv.append("\n"+recv_buff);
        }
    };

    private void send() {
        bt_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        send_buff = et_send.getText().toString();
                        //向服务器端发送消息
                        System.out.println("------------------------");
                        OutputStream outputStream=null;
                        try {
                            outputStream = socket.getOutputStream();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        if(outputStream!=null){
                            try {
                                outputStream.write(send_buff.getBytes());
                                System.out.println("1111111111111111111111");
                                outputStream.flush();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

                    }
                }).start();

            }
        });
    }

    private void initView() {
        et_send = (EditText) findViewById(R.id.et_send);
        bt_send = (Button) findViewById(R.id.bt_send);
        tv_recv = (TextView) findViewById(R.id.tv_recv);
    }
}

这里有几个地方需要特别注意:

1、创建socket时需要开一个子线程,而不能直接在主线程中完成,否则会报错

2、当接收来自树莓派服务器的消息时,需要刷新TextView,而刷新TextView的操作不能直接在子线程中完成,需要用Handler来实现,否则会报错,提示view只能由源线程来更改

整个项目需要先启动树莓派,然后手机连上树莓派的WIFI热点,如果想要查看树莓派的输出信息,则可以利用window的远程桌面连接树莓派,也可以用putty这个软件进行命令行控制,当然,有条件的完全可以用HDMI接口给你的树莓派连一个显示器

        
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树莓派与Android客户端进行socket通信 的相关文章

随机推荐

  • FSL图像计算基础命令:fslmaths, fslstats, fslmeants

    一 fslmaths fslmaths是一个功能非常强大的图像计算器 xff0c 可以用来执行各种各样的图像处理 span class token comment Usage fslmaths dt lt datatype gt lt fi
  • 第八届蓝桥杯个人省赛(软件类)C组第一题贪吃蛇长度

    题目如下 标题 xff1a 贪吃蛇长度 43 43 H
  • STM32串口下载程序(官方下载软件)

    ST官方有一款专门用于串口下载程序的下载软件STM32 Flash loader demonstrator FLASHER STM32 xff0c 目前的最新版本是V2 8 0版 xff0c 下载链接如下 xff1a https my st
  • 操作系统:生产者-消费者问题

    生产者 消费者问题 一 问题描述 系统中有一组生产者进程和消费者进程 xff0c 生产者进程每次生产一个产品放入缓冲区 xff0c 消费者进程每次从缓冲区中取出一个产品并使用 其中 xff0c 缓冲区的容量为n 上图是生产者 消费者问题的模
  • Ubuntu18.04 误删/usr/bin/python3的解决方案

    Ubuntu18 04 误删 usr bin python3的解决方案 这应该是一个链接文件 xff0c Python pip3等指令都会指向它 xff0c 删除之后无法打开Python解释器我在误删之后 首先重新下载了Python3 8
  • 对机器人的认知整理

    机器人的定义与特点 机器人是自动执行工作的机器装置 xff0c 可以接受人的指挥 运行预先编排的程序或者根据人工智能技术指定的原则纲领行动 机器人 包含传感器 执行器 xff0c 能够与物理世界交互 xff0c 可编程 xff0c 能够进行
  • 计算机图形学

    上课时间 xff1a 2 12周周二上午1 2 3节 Lesson1 9月15日 这堂课讲了第1 2 3章节 第一章 概述第二章 计算机图形硬件系统第三章 图形标准 第一章 概述 1 1 定义 计算机图形学是研究怎样用计算机生成 处理和显示
  • Unity导出apk出现的问题,JDK,Android SDK,NDK,无“安装模块”

    导出apk失败 使用unity导出apk文件 xff0c 会出现提示 xff1a 需要合适版本的JDK Android SDK和Android NDK xff0c 要找到 下载和安装好合适的版本非常耗费时间 xff0c 网上很多教程指出可以
  • 论文阅读:带有物体级重定位的视觉惯性多实例动态SLAM

    带有物体级重定位的视觉惯性多实例动态SLAM Ren Y Xu B Choi C L et al Visual Inertial Multi Instance Dynamic SLAM with Object level Relocalis
  • Ubuntu内存清理经验整理

    本文档用于整理记录清理ubuntu内存过程中的经验 首先 xff0c 可以使用内置程序 Disk Usage Analyzer 分析 xff0c 直观看到哪些文件夹占用内存较大 另外 xff0c 也可以使用指令du sh sort h查看当
  • 论文阅读 | LOAM:实时Lidar里程计和建图

    Zhang J Singh S LOAM Lidar odometry and mapping in real time C Robotics Science and Systems 2014 2 9 1 9 64 inproceeding
  • 一招解决由于找不到vcruntime140_1.dll,无法继续执行代码

    电脑系统丢失vcruntime140 1 dll文件 xff0c 会导致很多软件跟游戏打不开 xff0c 也无法运行 xff0c 比如常见的ps xff0c pr xff0c 吃鸡游戏等等 那需要我们怎么修复呢 xff1f 相信这个问题困扰
  • 终端/Vscode + GDB调试C++程序

    CMakeLists中需要设置编译类型为Debug set CMAKE BUILD TYPE Debug 下载gdb调试器 span class token function sudo span span class token funct
  • k8s节点加入集群

    k8s节点加入集群流程及常见问题 移除docker yum remove docker docker client docker client latest docker common docker latest docker latest
  • pulsar常用命令

    创建安全认证key bin pulsar tokens create secret key output data admin secret key 创建角色 xff0c 生成token bin pulsar tokens create s
  • 转-docker入门

    Docker入门教程 xff08 详细 xff09 JWei 7的博客 CSDN博客 docker 入门教程
  • 用Bmob实现用户数据添加和查询显示

    我用的例子利用Bmob云服务器实现了让用户上传待出售商品信息 xff0c 以及能浏览在售商品信息的小功能 刚接触Bmob感觉它确实好用 xff0c 但我不得不吐槽那个案例更新的太慢了 xff0c 新版本的SDK跟老版本还是有很大差别的 xf
  • linux中的文件移动

    Linux不同于Windows xff0c 在Windows操作系统中我们只需要傻瓜式的将文件用鼠标拖到目标文件夹即可 xff0c 但是在Linux中移动文件却不是那么的简单 以Ubuntu16 04为例说一下Linux中的文件的移动 1
  • android顶部回退按钮的实现

    最近看来好多关于android顶部导航栏回退的实现 如下图效果 点击返回上级页面 xff0c 网上的大部分都实现特别繁琐 xff0c 其实安卓自带BUFF 在Manifest清单文件中一句代码就能搞定 xff0c 特别easy xff0c
  • 树莓派与Android客户端进行socket通信

    首先 xff0c 需要对树莓派进行配置 xff0c 使其成为AP热点 xff0c 这里我用的树莓派3B自带wifi蓝牙模块 xff0c 树莓派3B作AP热点的方法具体参考https blog csdn net u014271612 arti