Android Tcp操作
Tcp是基于传输层的面向连接的可靠通讯协议,其优点是基于连接,使得服务端和客户端可以实现双向通信,且实时性高,在需要服务端主动向客户端推送数据的应用场景中,使用TCP协议是一种很好的方式。
初学Android,将Android中Tcp的使用方式记录一下,希望对新学Android开发的新同学有帮助,这里主要介绍TcpClient的使用,因为很少会用Android来建立TcpServer端。
这里主要介绍Tcp客户端的几个应用:
1.与服务器建立连接
2.向服务端发送数据
3.接收服务端返回的数据
4.断线重连机制
在Android中使用socket有两个地方需要注意的:
1.在AndroidMainfest.xml中需要添加对网络的权限支持
<uses-permission android:name="android.permission.INTERNET" />
2.Android中规定对socket的操作必须在线程中进行,如在主线程中进行操作会出现无法收发数据的情况。
(1)创建socket,与服务器建立连接
InetSocketAddress SerAddr = new InetSocketAddress(”192.168.1.100“,9988); //设置服务的IP地址和端口
try {
socket.connect(SerAddr,3000); //尝试连接服务器
}catch (Exception e){
}
(2)发送数据
try {
/注意采用utf-8编码确保中文传输不会乱码
BufferedWriter bufferedWriter =new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(),"utf-8"));
bufferedWriter.write(”Hello“);
bufferedWriter.flush();
}catch (Exception e){
}
(3)接收数据
try {
inputStream = new DataInputStream(socket.getInputStream());
if(inputStream.available()>0)
{
byte[] recData = new byte[inputStream.available()];
inputStream.read(recData);
String iText=new String(recData,"utf-8");
}
}catch (Exception e){
}
(4)断线重连
当保持长时间的连接时,难免会因为网络或其他原因导致客户端与服务端断开连接,所以代码里面应该定时的去检查连接状态,当连接断开时,
应该重新尝试连接服务端。我们这里可以使用socket.sendUrgentData(0xFF);函数来检测,当服务端断开时,连续三次调用此函数会出现异常。
我们可以根据是否出现异常来断定与服务器的连接情况。
try {
socket.sendUrgentData(0xFF);
}catch (Exception e){
socket.close(); //关闭套接字,重新创建新的并调用connect函数重新连接
socket = new Socket();
}
以下贴出TcpHelper类的具体代码:
public class TcpHelper{
private Socket socket;
private BufferedWriter bufferedWriter;
private DataInputStream inputStream;
private boolean NeedStop;
private InetSocketAddress SerAddr;
public String ErrMsg;
private ReadThread readThread; //读取数据线程
private OnReceiveEvent receiveEvent; //此事件用于当接收到数据时向主线程通知接收到的数据
private long LastCheckTime;
public static interface OnReceiveEvent{
public void ReceiveBytes(byte[] iData);
public void ReceiveString(String iData);
}
public enum EDataType{EDT_BYTE,EDT_STRING};
private EDataType dataType;
public TcpHelper(String HostIp,int HostPort) {
try {
LastCheckTime=System.currentTimeMillis();
readThread =new ReadThread();
NeedStop=false;
SerAddr = new InetSocketAddress(HostIp,HostPort);
NeedStop=false;
socket = new Socket();
readThread.start();
}catch (Exception e)
{
ErrMsg=e.getMessage();
}
}
public void SendString(String iText){ //发送字符串
dataType=EDataType.EDT_STRING;
toSend(iText);
}
public void SendBytes(byte[] iBuf){ //发送字节流指令
dataType=EDataType.EDT_BYTE;
String iText = new String(iBuf);
toSend(iText);
}
//发送数据线程
private void toSend(final String iText){
new Thread(
new Runnable() {
@Override
public void run() {
try {
bufferedWriter.write(iText);
bufferedWriter.flush();
} catch (Exception e) {
}
}
}
).start();
}
public boolean isConnected(){
return socket.isConnected();
}
//设置通知事件
public void setReceiveEvent(OnReceiveEvent iEvent){
receiveEvent=iEvent;
}
//读取线程
private class ReadThread extends Thread{
@Override
public void run() {
while (!NeedStop){
try {
if (!socket.isConnected() || socket.isClosed()){
socket.connect(SerAddr,3000);
if(bufferedWriter==null)
bufferedWriter =new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(),"utf-8"));
if(inputStream==null)
inputStream = new DataInputStream(socket.getInputStream());
}
else {
if(inputStream.available()>0){
byte[] recData = new byte[inputStream.available()];
inputStream.read(recData);
if(receiveEvent!=null)
{
if(dataType==EDataType.EDT_BYTE) {
receiveEvent.ReceiveBytes(recData);
}
else {
String s=new String(recData,"utf-8");
receiveEvent.ReceiveString(s);
}
}
}
if (System.currentTimeMillis()-LastCheckTime>5000)
{
try {
LastCheckTime=System.currentTimeMillis();
socket.sendUrgentData(0xFF);
}catch (Exception e){
socket.close();
socket = new Socket();
bufferedWriter=null;
inputStream =null;
}
}
}
}catch (Exception e){
}
}
}
}
}
测试Tcp连接的Activity代码:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView; public class TcpFormActivity extends Activity {
private TcpHelper tcpHelper;
private String SerIp;
private int SerPort;
private EditText InputMsg;
private TextView RecMsg;
private String TcpRecData;
private MyHandler handler;
private TcpReceive tcpReceive;
@Override
protected void onCreate(Bundle saveInstanceState){
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_tcpform);
RecMsg = (TextView)findViewById(R.id.TVTcpData);
InputMsg = (EditText)findViewById(R.id.EdtTcpMsg);
}
public class TcpReceive implements TcpHelper.OnReceiveEvent{
public synchronized void ReceiveBytes(byte[] iData){
}
public synchronized void ReceiveString(String iData){
TcpRecData=iData;
Message msg=new Message();
msg.what=1;
handler.sendMessage(msg);
}
}
class MyHandler extends Handler {
public MyHandler() {
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
RecMsg.append(TcpRecData); //接收到数据显示到TextView上
break;
}
super.handleMessage(msg);
}
}
public void onConnectClick(View view){
if(tcpHelper==null)
{
SerIp = ((EditText)findViewById(R.id.EdtTcpSerIp)).getText().toString();
SerPort =Integer.parseInt(((TextView)findViewById(R.id.EdtTcpPort)).getText().toString());
tcpHelper = new TcpHelper(SerIp,SerPort);
tcpReceive = new TcpReceive();
tcpHelper.setReceiveEvent(tcpReceive);
handler = new MyHandler();
}
}
public void onSendMsgClick(View view){
try {
String iText=InputMsg.getText().toString();
tcpHelper.SendString(iText);
}catch (Exception e)
{ }
}
}
Android Tcp操作的更多相关文章
- android tcp通讯
Andoird TCP通讯 前言 最近在写一个即时通讯的项目,有一些心得,写出来给大家分享指正一下. 简单描述一下这个项目: 实时查询车辆运行状态的项目,走TCP通迅. 接口采用GZIP压缩. 后台是 ...
- [Android Pro] 完美Android Cursor使用例子(Android数据库操作)
reference to : http://www.ablanxue.com/prone_10575_1.html 完美 Android Cursor使用例子(Android数据库操作),Androi ...
- Android 常用操作
0.android studios使用介绍 使用介绍 android studio 常用小技巧 网址 1.怎么样添加第三方库 方法一: 第一步:将第三方库以module的形式导入 第二步:选中要导入第 ...
- Android – 学习操作NFC – 2
在<Android – 学习操作NFC – 1>说明了Android在处理NFC tag的机制.tag dispatch system的运作流程,以及三种ACTION_NDEF_DISCO ...
- android 文件操作类简易总结
android 文件操作类(参考链接) http://www.cnblogs.com/menlsh/archive/2013/04/02/2997084.html package com.androi ...
- 为什么说android UI操作不是线程安全的
转载于:http://blog.csdn.net/lvxiangan/article/details/17218409#t2 UI线程及Android的单线程模型原则 使用Worker线程 Commu ...
- Android权限操作之uses-permission详解
本文实例讲述了Android权限操作之uses-permission.分享给大家供大家参考,具体如下: 我们在安装Android软件的时候,系统会提示该软件所需要的权限,相对于其他系统,android ...
- android TCP 和 UDP总结(转)
之前写过一些关于TCP和UDP数据传输的代码,比如使用TCP传输音视频数据包,P2P打洞中使用UDP等.写好之后就直接丢下了,没有总结下都.最近准备找工作,再拿来温习下. 1.还是先说点啥 暂时把自己 ...
- 22-ESP8266 SDK开发基础入门篇--编写Android TCP客户端 , 连接和断开
https://www.cnblogs.com/yangfengwu/p/11192618.html 有些很细致的东西参考这篇 https://www.cnblogs.com/yangfengwu ...
随机推荐
- python 根据字符串语句进行操作再造函数(evec和eval方法)
例: #coding:utf-8 ''' Created on 2017年9月9日 @author: Bss ''' test_list=['def','a',''] test_list1=['pri ...
- vue饿了么UI库-笔记
1. :rules="{required: true, message: '有效期不能为空'}" :rules="{type:'date',required: true, ...
- vue中点击不同的em添加class去除兄弟级class
vue中使用v-for循环li 怎么点击每个li中的em给添加class删除兄弟元素 <html lang="en"> <head> <meta ch ...
- (尚018-第二章2.1)Vue使用vue-cli创建模板项目
2.1.1 1)vue-cli是官方提供的脚手架工具(注意:脚手架本身是个库) 2)github:https://github.com/vuejs/vue-cli 3)作用:从https://gith ...
- 微信小程序底部导航栏部署
在微信小程序开发app.json(app.json它是定义全局页面) 只是用来部署微信底部的图标,最多不能大于五个 "tabBar":{ "selectedColor&q ...
- 【批处理】choice命令,call 命令,start 命令,rem
[1]choice命令简介 使用此命令可以提示用户输入一个选择项,根据用户输入的选择项再决定执行具体的过程. 使用时应该加/c:参数,c: 后应写提示可输入的字符或数字,之间无空格.冒号是可选项. 使 ...
- amundsen 来自lyft 的开源数据发现平台
amundsen 是来自lyft 开源的元数据管理.数据发现平台,功能点很全,有一个比较全的前端.后端以及 数据处理框架 参考架构图 说明 从官方介绍以及github代码仓库可以看出还是比较全的整体解 ...
- 限流神器之-Guava RateLimiter 实战
前段时间,项目中需要对某些访问量较高的路径进行访问并发数控制,以及有些功能,比如Excel导出下载功能,数据量很大的情况下,用户不断的点击下载按钮,重复请求数据库,导致线上数据库挂掉.于是在这样的情况 ...
- [CSP-S 2019]括号树
[CSP-S 2019]括号树 源代码: #include<cstdio> #include<cctype> #include<vector> inline int ...
- windows批量删除当前目录以及子目录的所有空文件夹
在桌面创建一个记事本,将以下内容复制粘贴到记事本中,将记事本的拓展名修改为bat即可,然后将该文件放到需要执行的目录双击. @echo off setlocal enabledelayedexpans ...