在工科类项目中,嵌入式系统与软件系统或后台数据库之间的信息传输是实现“物联网”的一种必要的途径,对已简单概念的物联网,通常形式都是一个单片机/嵌入式系统实现数据的采集及其处理,通过蓝牙,wifi或者是ZigBee等无线模块进行传输,再由一些软件端来显示数据实现人机交互。

  例如在进行的一个项目中,需要在stm32上获取位置的信息,再传输到移动设备或者电脑端来显示数据,选用wifi来作为传输媒介,那么就要考虑wifi间数据传输的形式——TCP或者UDP传输。

  简单记录一下在实际开发中,利用Android平台下TCP/IP协议来实现与搭载WIFI模块的硬件系统进行通信的程序设计与实现。

  设计一个界面,三个EditText,两个Button,还有一个用于显示的TextView;整体使用LinearLayout的布局(个人喜好,结构清晰)

  程序如下:

<?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:gravity="center"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"> <LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:hint="IP地址"
android:id="@+id/IPAddress"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:hint="端口号"
android:id="@+id/port"
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/connect"
android:text="开始连接"
/> <EditText
android:hint="输入需要发送的信息"
android:id="@+id/sendData"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> <Button
android:id="@+id/send"
android:text="发送数据"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <TextView
android:background="#eeeeee"
android:id="@+id/information"
android:layout_width="match_parent"
android:layout_height="match_parent" /> </LinearLayout>

  实现一个大致的界面,如下所示:

  接下来是功能实现部分,在TCP/IP协议的网络连接,需要两个主要信息:IP地址,以及端口号。

  在JAVA环境下,TCP连接是相对简洁的,这也是JAVA的一个优点:

  Socket socket=new Socket(IP_Address,Port);

  一句简单的话就可以实现网络连接。

  还需要一个BufferedReader和一个PrintWriter来实现数据的传输,当Socket操作完成之后,对其进行设定:

mBufferedReaderClient = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
mPrintWriterClient = new PrintWriter(mSocket.getOutputStream(),true);

  然后开辟其它线程来实现数据的传输以及一些视图的更新。

  java部分代码如下:

package com.example.hp.acceleration;

import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket; public class MainActivity extends AppCompatActivity { private Button mButtonConnect;
private Button mButtonSend;
private TextView mTextViewMessage;
private boolean isConnect;
private String Information;
private EditText mEditTextIP;
private EditText mEditTextPort;
private EditText mEditTextSendData; private Socket mSocket=null;
private BufferedReader mBufferedReaderClient=null;
private PrintWriter mPrintWriterClient=null; private String IP="";
private int port; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()//磁盘读取操作
.detectDiskWrites()//磁盘写入操作
.detectNetwork()//网络操作
.penaltyLog()//在Logcat中打印违规异常信息
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()//泄露的SqLite对象
.penaltyLog()
.penaltyDeath()
.build()); mButtonConnect=(Button)findViewById(R.id.connect);
mButtonSend=(Button)findViewById(R.id.send);
mTextViewMessage=(TextView)findViewById(R.id.information);
mEditTextIP=(EditText)findViewById(R.id.IPAddress);
mEditTextPort=(EditText)findViewById(R.id.port);
mEditTextSendData=(EditText)findViewById(R.id.sendData); mTextViewMessage.setMovementMethod(ScrollingMovementMethod.getInstance());
mTextViewMessage.setTextIsSelectable(true); isConnect=false;
mButtonSend.setEnabled(false); mButtonConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isConnect)
{
isConnect=false;
mButtonConnect.setText("开始连接");
mButtonSend.setEnabled(false);
mTextViewMessage.setText("");
if(mSocket!=null) {
try {
mSocket.close();
} catch (IOException e) { }
}
}else{
isConnect=true;
mButtonConnect.setText("断开连接"); mButtonSend.setEnabled(true);
IP=mEditTextIP.getText().toString();
String portString=mEditTextPort.getText().toString();
if (portString.length()>1){
port=Integer.valueOf(portString);
}
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
try {
mSocket=new Socket(IP,port);
mBufferedReaderClient = new BufferedReader(new InputStreamReader
(mSocket.getInputStream()));
mPrintWriterClient = new PrintWriter(mSocket.getOutputStream(),
true);
Message msg=new Message();
msg.what=0;
mHandler.sendMessage(msg);
}catch (IOException e) {
mTextViewMessage.setText("error");
}
char[] buffer=new char[256];
int num=0;
while (isConnect)
{
try{
if ((num=mBufferedReaderClient.read(buffer))>0) {
Information=getInfoBuff(buffer,num);
Message msg=new Message();
msg.what=1;
mHandler.sendMessage(msg);
}
}catch (Exception e) {
}
} }
});
if (IP.length()>1&&portString.length()>=1)
{
thread.start();
}else
{
mTextViewMessage.setText("IP地址错误或端口号错误");
} }
}
}); mButtonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
try {
String string=mEditTextSendData.getText().toString();
mPrintWriterClient.print(string);
mPrintWriterClient.flush();
}catch (Exception e){
}
}
});
thread.start();
}
}); }
private String getInfoBuff(char[] buff,int count){
char[] temp=new char[count];
for(int i=0;i<count;i++){
temp[i]=buff[i];
}
return new String(temp);
} Handler mHandler=new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
if (msg.what==0){
Toast.makeText(MainActivity.this,"连接成功!",Toast.LENGTH_SHORT).show();
}
else if (msg.what==1){
mTextViewMessage.append(Information+"\r\n"); }
}
}; }

  最后一点,在Android环境下,需要在AndroidManifest.xml文件下赋予权限

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

  以上几个权限是Android使用wifi进行TCP协议下通讯必须的几个。

Android平台下的TCP/IP传输(客户端)的更多相关文章

  1. Android平台下Dalvik层hook框架ddi的研究

    通过adbi,可以对native层的所有代码进行hook.但对于Android系统来说,这还远远不够,因为很多应用都还是在Dalvik虚拟机中运行的. 那么,有没有什么办法可以对Dalvik虚拟机中跑 ...

  2. [转帖]Android平台下OpenGL初步

    原文请看 Android平台下OpenGL初步 本文只关注于如何一步步实现在Android平台下运用OpenGl. 1.GLSurfaceView GLSurfaceView是Android应用程序中 ...

  3. 网络编程TCP/IP实现客户端与客户端聊天

    一.TCP/IP协议 既然是网络编程,涉及几个系统之间的交互,那么首先要考虑的是如何准确的定位到网络上的一台或几台主机,另一个是如何进行可靠高效的数据传输.这里就要使用到TCP/IP协议. TCP/I ...

  4. android 网络编程--socket tcp/ip udp http之间的关系

    网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层,一般编程人员接触最多的就是应用层和运输层,再往下的就是所谓的媒体层了,不是我们研究的对象. 下面是应用层.运输层,网络 ...

  5. 前端工程师如何理解 TCP/IP 传输层协议?

    网络协议是每个前端工程师都必须要掌握的知识,TCP/IP 中有两个具有代表性的传输层协议,分别是 TCP 和 UDP,本文将介绍下这两者以及它们之间的区别. TCP/IP网络模型 计算机与网络设备要相 ...

  6. Android平台下OpenCV移植与使用---基于C/C++

    在<Android Studio增加NDK代码编译支持--Mac环境>和<Mac平台下Opencv开发环境搭建>两篇文章中,介绍了如何使用NDK环境和Opencv环境搭建与测试 ...

  7. 本学习笔记TCP/IP传输协议

    一个.通过网络发送数据,大致能够分为面向有连接与面向无连接两种类型: 1.面向无连接型包含以太网. IP.UDP等协议. 2. 面向有连接 型包含ATM.帧中继.TCP等 协议. 通过一张图了解一下: ...

  8. TCP/IP传输层,你懂多少?

    1. 传输层的主要功能是什么?2. 传输层如何区分不同应用程序的数据流?3. 传输层有哪些协议?4. 什么是UDP协议?5. 为什么有了UDP,还需要TCP?6. 什么是TCP协议?7. 怎么理解协议 ...

  9. 面试热点|理解TCP/IP传输层拥塞控制算法

    0x00.前言 通过本文你将了解到以下内容: 拥塞控制概念以及其背景 流量控制和拥塞控制的区别与联系 拥塞控制主要过程详解 伙伴们认真学习一下,让offer来得更猛烈些吧! 0x01.TCP/IP协议 ...

随机推荐

  1. Java 入门作业

  2. nvcc fatal : Unsupported gpu architecture 'compute_11'

    使用VS编译OpenCV编译源代码时候,对Cmake生成的工程文件编译,会出现 nvcc fatal : Unsupported gpu architecture 'compute_11'  问题.原 ...

  3. 使用Visio—UML画类图

    在一个VS工程中,由于类的个数较多,而参数描述不是特别清晰.若此工程的生命周期较长,则有必要对工程进行完整分析,给出完整的文档.需要画出类图,并对每个成员进行详细描述. 一.画出类图 在VIsio中, ...

  4. 慕课网页面app的滑动

    #coding=utf-8from appium import webdriver def get_driver(): desc={ "platformName":"An ...

  5. 在阿里云的ubuntu服务器上安装xampp时出现unable to realloc unable to realloc 8380000 bytes错误

    在阿里云的ubuntu服务器上安装xampp时出现unable to realloc unable to realloc 8380000 bytes错误 解决:增加Swap空间(阿里云缺省没有分配任何 ...

  6. DOM学习之图片库切换效果

    addloadevent(prepareplaceholder()) addloadevent(prepareGallery()) //页面加载完时执行函数 function addloadevent ...

  7. 数据类型 scanf标准函数 sizeof关键字 二进制(day03)

    字符类型的名称是char 字符类型里包含256个不同的整数,每个 整数对应一个字符(例如'a', '^'等) 这些整数和字符完全可以互相替代 ASCII码表列出所有整数和字符的对应关系 ASCII码表 ...

  8. [jzoj 5776]【NOIP2008模拟】小x游世界树 (树形dp)

    传送门 Description 小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当他想前往阿瓦隆时发现那里只有圣诞节时才能到达 ...

  9. SQL中的条件判断语句(case when zhen if,ifnull)用法

    简介: case具有两种格式.简单case函数和case搜索函数.这两种方式,可以实现相同的功能.简单case函数的写法相对比较简洁,但是和case搜索函数相比,功能方面会有些限制,比如写判定式.还有 ...

  10. 44.mapping下的数据结构

    主要知识点 1.了解es核心的数据类型 2.了解es默认的mapping方式 3.查看mapping     1.核心的数据类型     string,text byte, short,integer ...