在上章14.Android-使用sendMessage线程之间通信我们学习了如何在线程之间发送数据.

接下来我们便来学习如何通过socket读写TCP.

需要注意的是socket必须写在子线程中,不能在ui主线程中直接使用,所以我们这里创建了两个class:

MainActivity(主界面)、TcpThread(获取socket接收的数据)

由于代码有注释了,所以就不解释了.

1.gif效果如下

2.activity_main.xml如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <EditText
android:id="@+id/et_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:hint="请填入要发送的内容"
/> <Button
android:id="@+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/et_text"
android:text="发送"
/> <TextView
android:id="@+id/tv_recv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/btn_send"
android:minLines="20"
android:hint="接收的内容"
/>
</RelativeLayout>

3.MainActivity.java如下所示

package com.example.tcpdemo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; public class MainActivity extends Activity { TcpThread mt; TextView tv_recv;
EditText et_text; //要发送的内容
Button btn_send; //定义一个handler
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
//打印服务器端发来的消息
System.out.println("read:"+msg.obj.toString());
tv_recv.append(msg.obj.toString()+"\r\n");
};
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); tv_recv = (TextView)findViewById(R.id.tv_recv);
et_text = (EditText)findViewById(R.id.et_text); mt = new TcpThread();
mt.setHandler(mHandler); //设置handler
mt.setIp("10.10.10.104"); //设置服务器地址
mt.start(); //启动线程 btn_send = (Button)findViewById(R.id.btn_send); btn_send.setOnClickListener(new OnClickListener() { //向服务器端发送数据
public void onClick(View v) { if(!mt.write(et_text.getText().toString()))
{
Toast.makeText(getApplicationContext(), "发送失败", Toast.LENGTH_SHORT).show(); }
}
});
}
}

4.TcpThread.java如下所示

package com.example.tcpdemo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException; import android.os.Handler;
import android.os.Message; public class TcpThread extends Thread { Handler mHandler=null;
Socket socket = null;
String ip = null;
OutputStream outputStream = null; //输出流
InputStream inputStream=null; //接收流
//获取另一个线程的Handler
public void setHandler( Handler handler){
mHandler = handler;
} //设置服务器IP
public void setIp(String ip){
this.ip = ip;
} public void run(){ try {
socket = new Socket(ip, 8080); //访问指定的ip地址:8080

// 1 UnknownHostException:如果无法识别主机的名字或IP地址,就会抛出这种异常。
// 2 ConnectException:如果没有服务器进程监听指定的端口,或者服务器进程拒绝连接,就会抛出这种异常。
// 3 SocketTimeoutException:如果等待连接超时,就会抛出这种异常。
// 4 BindException:如果无法把Socket对象与指定的本地IP地址或端口绑定,就会抛出这种异常

                } catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} //获取输出流
try {
outputStream = socket.getOutputStream(); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try{
while (true) //读取服务器端发送来的数据
{
final byte[] buffer = new byte[1024];//创建接收缓冲区
inputStream = socket.getInputStream();
final int len = inputStream.read(buffer);//数据读出来,并且返回数据的长度
if(len>0)
{
Message msg = mHandler.obtainMessage();
//设置发送的内容
msg.obj = new String(buffer,0,len);
mHandler.sendMessage(msg);
} }
}
catch (IOException e) { } } //向服务器端写入数据
public boolean write(String text){ boolean ret = true;
try {
outputStream.write(text.toString().getBytes());
} catch (IOException e) {
ret = false;
e.printStackTrace();
}
return ret;
}
}

 注意1:

使用inputStream.read(buffer)的时候如果读取不到数据,会进入阻塞状态,直到有数据来了,才会退出执行下个语句.如果想不使用阻塞的话,可以通过if(inputStream.available()>0)来判断是否有数据来了.再读取即可

15.Android-实现TCP客户端,支持读写的更多相关文章

  1. android 之TCP客户端编程

    补充,由于这篇文章是自己入门的时候写的,随着Android系统的升级可能有发送需要在任务 中进行,如有问题请百度 thread 或者看下面链接的文章 https://www.cnblogs.com/y ...

  2. android之TCP客户端框架

    一.程序框架 1.1 创建方法 onCreate 1.1.1 创建连接按键线程,并使能线程(触发原因:可按键.其他操作,并进行状态判断): Connect_Thread connect_Thread ...

  3. Android之TCP服务器编程

    推荐一个学java或C++的网站http://www.weixueyuan.net/,本来想自己学了总结出来再写博客,现在没时间,打字太慢!!!!,又想让这好东西让许多人知道. 关于网络通信:每一台电 ...

  4. 24-ESP8266 SDK开发基础入门篇--Android TCP客户端.控制 Wi-Fi输出PWM的占空比,调节LED亮度

    https://www.cnblogs.com/yangfengwu/p/11204436.html 刚才有人说需要点鸡汤.... 我想想哈;我还没问关于哪方面的鸡汤呢!!! 我所一直走的路线 第一: ...

  5. 23-ESP8266 SDK开发基础入门篇--编写Android TCP客户端 , 加入消息处理

    https://www.cnblogs.com/yangfengwu/p/11203546.html 先做接收消息 然后接着 public class MainActivity extends App ...

  6. Android仿人人客户端(v5.7.1)——新鲜事之完整篇

    转载请标明出处: http://blog.csdn.net/android_ls/article/details/9228083       声明:仿人人项目,所用所有图片资源都来源于其它Androi ...

  7. 【RL-TCPnet网络教程】第14章 RL-TCPnet之TCP客户端

    第14章      RL-TCPnet之TCP客户端 本章节为大家讲解RL-TCPnet的TCP客户端实现,学习本章节前,务必要优先学习第12章TCP传输控制协议基础知识.有了这些基础知识之后,再搞本 ...

  8. 10-51单片机ESP8266学习-AT指令(ESP8266连接路由器,建立TCP服务器,分别和C#TCP客户端和AndroidTCP客户端通信+花生壳远程通信)

    http://www.cnblogs.com/yangfengwu/p/8871464.html 先把源码和资料链接放到这里 源码链接:https://pan.baidu.com/s/1wT8KAOI ...

  9. --系统编程-网络-tcp客户端服务器编程模型、socket、htons、inet_ntop等各API详解、使用telnet测试基本服务器功能

    PART1 基础知识 1. 字节序 网络字节序是大端字节序(低地址存放更高位的字节), 所以,对于字节序为小端的机器需要收发网络数据的场景,要对这些数据进行字节序转换. 字节序转换函数,常用的有四个: ...

随机推荐

  1. 最强PostMan使用教程

    最近需要测试产品中的REST API,无意中发现了PostMan这个chrome插件,把玩了一下,发现postman秉承了一贯以来google工具强大,易用的特质.独乐乐不如众乐乐,特此共享出来给大伙 ...

  2. 4、python基础语法

    前言:本文主要介绍python的一些基础语法,包括标识符的定义.行和缩进.引号和注释.输入输出.变量的定义. 一.标识符 1.凡是我们自己取的名字,都是标识符. 2.在Python里,标识符由字母.下 ...

  3. UVA 最大面积最小三角形剖分

    点击打开题目 题目大意: 以顺时针或逆时针给出一个简单多边形的n个点的坐标,用n-2条互不相交的,且与边不相交的对角线,分成n-2个三角形,要求其中最大三角形的面积最小 开始还汪星人咬乌龟,无从下口, ...

  4. makefile自动依赖生成

    自动依赖生成 基于make的构建环境要正确工作, 一个很重要(也很烦人)的任务是, 在makefile中正确列 举依赖. 这个文档将介绍了一个非常有用的让make自身来创建和维护这些依赖的方法. 文章 ...

  5. linux开机无法进入桌面直接进入initramfs模式的问题修复

    可能是因为关机异常导致磁盘错误. kali linux升级到2019.4版本之后出现过好几次异常关机导致直接进入initramfs的模式,无法进入系统桌面,网上的办法基本上也都是无效的,前几次翻了很多 ...

  6. 线段树+Lazy标记(我的模版)

    #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ...

  7. STM8 ADC 多个通道连续扫描缓冲区数据带中断模式的正确写法

    近日调试了STM8S的ADC采集多通道数据的程序,按照之前的立即,将ADC1设置为:扫描模式,连续采集,数据缓存模式,中断使能后应该可以在中断后读取到数值了,可是无论怎样都只能读取到第一个缓冲器的数据 ...

  8. 表单提交,action 地址问题

    jsp 页面如下: <%@ page contentType="text/html;charset=UTF-8" language="java" %> ...

  9. mysql-cluster集群搭建步骤

    1.从官网下载mysql-cluster安装包: https://dev.mysql.com/downloads/cluster/ 2.解压安装包 #上传到服务器目录/usr/softwares并解压 ...

  10. 手把手写框架入门(一) | 核心拦截器DispatchFilter实现

    前言 1Filter实现框架拦截 1配置自定义Filter 2创建一个Filter 3创建一个ActionMapping 4创建一个ActionMapper 5创建一个WebExecutor 6创建测 ...