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)
{ }
}
}
 

最新文章

  1. 修改applicationhost.config允许外部访问
  2. mysql创建数据库
  3. java Jsoup 抓取页面数据
  4. 改善C#程序的建议3:在C#中选择正确的集合进行编码
  5. Selenium 新手入门(C#)1. 用vs运行调用Selenium打开页面
  6. 装多系统删除某个系统后,如何恢复ubuntu引导
  7. iOS -数据持久化之CoreData
  8. 【Python】分布式任务队列Celery使用参考资料
  9. W5500问题集锦(持续更新中)
  10. iOS ui界面vtf 开发
  11. Backbone一些参考资源
  12. jquery之stop()的用法
  13. CRM odata方法如何使用$top
  14. redhat linux使用Centos yum源
  15. Eclipse报错 due to restriction on required library C:/Java/jdk1.7.51/jre/lib/rt.jar 解决方案
  16. 【转】npm包管理器那些事
  17. 记一次DDOS攻击防御实录
  18. css3新单位vw、vh、vmin、vmax的使用详解(转载)
  19. 如何使用$.each()与$().each()以及他们的区别
  20. Excel技巧--反向查询

热门文章

  1. fastjson异常(字符串集合转成字符串数组)
  2. 浏览器-同源政策(same-origin policy)
  3. 学习Microsoft Visio(3)
  4. 微信小程序——选择某个区间的数字
  5. gin内置验证器使用
  6. SpringBoot第三节(thymeleaf的配置与SpringBoot注解大全)
  7. c++ 将float 类型转换成string 类型
  8. js解决大文件断点续传
  9. Postgresql 数据库迁移步骤
  10. C++通过迭代修改字符串本身(auto类型说明符)