zoukankan      html  css  js  c++  java
  • 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)
    {

    }
    }
    }
     
  • 相关阅读:
    hbase java api
    hbase
    误删/usr文件夹解决办法
    死锁问题 代码示例
    H2O 生成 多线程并发控制 Semaphore
    多线程 打印零与奇偶数
    多线程交替打印 采用Semaphore
    多线程按顺序执行
    判断回文数
    整数反转
  • 原文地址:https://www.cnblogs.com/WushiShengFei/p/7397947.html
Copyright © 2011-2022 走看看