Android客户端利用Socket进行通信

上一篇https://blog.csdn.net/Haienzi/article/details/79808077介绍了java服务器端的相关操作。这一篇主要向大家介绍Android客户端的相关实现步骤。

基本步骤:

  • 用服务器端的IP地址和端口号实例化Socket对象。
  • 调用connect方法,连接到服务器上。
  • 将要发送到服务器的IO流填充到IO对象中,比如DataInputStream,DataOutputStrwam。
  • 调用Socket提供的getInputStream和getOutputStream方法,通过IO流对象,向服务器发送数据流。
  • 通讯完毕后,关闭打开的IO对象和Socket.

客户端说明

客户端涉及多个页面,都要和服务器进行通信,可以写一个消息监听接口,用于监听服务器端传递的消息。(这个监听接口很重要,下面会详细说明)

  • MessageListener.java
/**
 * 消息监听接口
 * Created by mqh on 2017/10/30.
 */
public interface MessageListener {
    public void Message(String msg);
}
  • Client.java
import java.net.Socket;

public class Client {
    private int port;//端口号
    private String address = null;//地址
    private Socket mSocket;//Socket对象
    private ClientThread clientThread;//客户端线程
    public void setSocket(Socket socket) {
        this.mSocket = socket;
    }
    public Client()
    {}

    public Client(String ip,int port)
    {
        this.address = ip;
        this.port = port;
    }
    public boolean start() {
        try {
            //实例化socket对象
            mSocket = new Socket(address,port);
            Log.d("testServer","client start,ip:"+address+",port:"+port);
            if (mSocket.isConnected()) {
                System.out.println("Connected..");
                //开启对应的客户端线程
                clientThread = new ClientThread(mSocket);
                clientThread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    // 直接通过client得到读线程
    public ClientInputThread getClientInputThread() {
        return clientThread.getIn();
    }

    // 直接通过client得到写线程
    public ClientOutputThread getClientOutputThread() {
        return clientThread.getOut();
    }

    // 直接通过client停止读写消息
    public void setIsStart(boolean isStart) {
        clientThread.getIn().setStart(isStart);
        clientThread.getOut().setStart(isStart);
    }
   public class ClientThread extends Thread {

       private ClientInputThread in;//读线程
       private ClientOutputThread out;//写线程

       public ClientThread(Socket socket) {
           in = new ClientInputThread(socket);
           out = new ClientOutputThread(socket);
       }
       //开启读线程和写线程
       public void run() {
           in.setStart(true);
           out.setStart(true);
           in.start();
           out.start();
       }

       // 得到读消息线程
       public ClientInputThread getIn() {
           return in;
       }

       // 得到写消息线程
       public ClientOutputThread getOut() {
           return out;
       }
   }

}
  • ClientInputThread.java
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
 * Created by mqh on 2017/10/30.
 */
public class ClientInputThread extends Thread {
    private Socket mSocket;
    private boolean isStart = true;
    private DataInputStream inputStream;// 对象输入流
    private InputStreamReader iReader;
    private String msg;
    private MessageListener mMessageListener;//消息监听接口

    public ClientInputThread(Socket socket)
    {
        this.mSocket = socket;
        try{
            inputStream = new DataInputStream(socket.getInputStream());// 实例化数据输入流
        }catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    //设置消息监听对象
    public void setMessageListener(MessageListener messageListener)
    {
        this.mMessageListener = messageListener;
    }
    public void setStart(Boolean isStart)
    {
        this.isStart = isStart;
    }
    @Override
    public void run() {
        try {
            System.out.println("Input isStart: " + isStart);
            while (isStart) {
                //接收从服务器发送过来的消息
                iReader = new InputStreamReader(inputStream, "UTF-8");
                //缓冲数组
                char[] buffer = new char[1024];
                int count = 0;
                StringBuffer sBuilder = new StringBuffer();
                while ((count = iReader.read(buffer,0,buffer.length))>-1) {
                    sBuilder.append(buffer,0,count);
                    if(count<1024)
                    {
                        break;
                    }
                }
                //将消息传递给监听器 (发送给需要的页面)
                mMessageListener.Message(sBuilder.toString());
            }
            if(inputStream !=null)
            {
                inputStream.close();
            }
            if (mSocket != null)
                mSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • ClientOutputThread.java
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
 * Created by mqh on 2017/10/30.
 */
public class ClientOutputThread extends Thread {
    private Socket socket;
    private DataOutputStream dataOutputStream;
    private OutputStreamWriter oStreamWriter;
    private boolean isStart = true;
    private String msg;//发送给服务器的消息

    public ClientOutputThread(Socket socket) {
        this.socket = socket;
        try {
            dataOutputStream = new DataOutputStream(socket.getOutputStream());// 在构造器里面实例化对象输出流
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setStart(boolean isStart) {
        this.isStart = isStart;
    }

    // 这里处理跟服务器是一样的 设置发送给服务器的消息
    public void setMsg(String msg) {
        this.msg = msg;
        synchronized (this) {
            notify();
        }
    }

    @Override
    public void run() {
        try {
            while (isStart) {
                if (msg != null) {
                    if (socket == null)
                        return;
                        //构建输出流对象
                    oStreamWriter = new OutputStreamWriter(dataOutputStream, "UTF-8");
                    StringBuffer sBuilder = new StringBuffer();
                    sBuilder.append(msg);
                    //将消息发送给服务器
                    oStreamWriter.write(sBuilder.toString());
                    oStreamWriter.flush();
                    synchronized (this) {
                        wait();// 发送完消息后,线程进入等待状态
                    }

                }
            }
            if(oStreamWriter != null)
            {
                oStreamWriter.close();
            }
            if (dataOutputStream != null)// 循环结束后,关闭流,释放资源
                dataOutputStream.close();
            // 循环结束后,关闭输出流和socket
            if (socket != null)
                socket.close();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

而且Android客户端在用户已经登陆的情况下需要一直向服务器传递消息,所以,想要保持与服务器的长连接,可以通过创建后台服务来实现。当应用打开时,开启后台服务,在后台服务中发送和接收与服务器通信的消息,它不会因为界面的切换,应用程序的切换而轻易中断。

你可能感兴趣的:(Android)