Android安卓TCP Socket通信实现Demo(附Apk源码) - Crazy程序猿

时间:2024-03-08 12:13:37

Android安卓TCP Socket通信实现Demo(附Apk源码)

本文主要讲解安卓(Android)TCP Socket通讯客户端(Client)和服务器(Server)Demo的实现(附源码),要注意BufferedReader的readLine()方法【((line = br.readLine()) != null)】 的阻塞问题,以及对接硬件的项目数据在十六进制&&byte&&int的转换处理。

大坑

最近有个项目需要用到TCP Socket通讯,遇到了一个大坑,所以做了这个Demo。
读取socket输入流的时候很多代码都会这么写,一般也不会有什么问题,但是readLine()方法读取不到换行和回车时会阻塞!
String line = null;
while ((line = br.readLine()) != null) {
}
readLine()是个阻塞函数,可以点进去查看源码,只有遇到换行或者回车回车符(’\n’,’\r’ 对应十六进制是 0D 0A)才会返回,而有些模块返回给你的数据不带这两个结束符,所以导致阻塞,程序不能走下去。这种情况一般如果模块那边愿意修改加上结束符,那就没问题。如果模块那边又不方便改,那就不能用这种方式了,得换种写法。

调试工具

调试的实时我们可以借助一些PC端的工具,TCP调试助手、TCP测试工具类似的,度娘下很多,操作也是傻瓜式的,填写IP和端口然后建立或者连接。
在这里插入图片描述

Demo演示及实现

废话少说,直接 进入今天的主题,下面就看看如何在Android上利用TCP/IP协议使用Socket与Server进行通讯吧!
在这里插入图片描述

一、权限

 <uses-permission android:name="android.permission.INTERNET"/>

二、服务端实现,简单来说就3步

1、 创建ServerSocket ,监听端口,等待客户端Socket连接
2、从Socket里获取的客户端发来的消息
3、通过Socket给客户端发消息

核心代码如下

class ServerSocketThread extends Thread {

	@Override
	public void run() {
		try {  
           // 创建ServerSocket  
           ServerSocket serverSocket = new ServerSocket(9999);  
           System.out.println("--开启服务器,监听端口 9999--");  
 
           // 监听端口,等待客户端连接  
           while (true) {  
               System.out.println("--等待客户端连接--");  
               Socket socket = serverSocket.accept(); //等待客户端连接  
               System.out.println("得到客户端连接:" + socket);  
                 
               startReader(socket);  
           }  
 
       } catch (IOException e) {  
           e.printStackTrace();  
       } 
	}
}

   /**  
    * 从参数的Socket里获取消息 
    */  
   private static void startReader(final Socket mSocket) {  
       new Thread(){  
           @Override  
           public void run() {  
               try {  
                   // 获取读取流  
                   BufferedReader in = new BufferedReader(new InputStreamReader(mSocket.getInputStream(),"utf-8"))
				   String line="";
				   while ((line = in.readLine()) != null) {// 读取数据  
                       System.out.println("*等待客户端输入*");  
                       System.out.println("获取到客户端的信息:" + line);
				    }
               } catch (IOException e) {  
                   e.printStackTrace();  
               }  
           }  
       }.start();  
   } 

 //通过socket来给客户端发送消息
 private void serverSendMessage(String mServerSendMessage) {
     new Thread() {
         @Override
         public void run() {
             PrintWriter out;
             try {
                 out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);
                 out.println(mServerSendMessage);
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }.start();
  }

三、客户端实现,跟服务器端流程类似

1、与服务器建立Socket连接
2、获取到输入输出流
3、收/发送消息

//与服务器建立连接
Socket mClientSocket = new Socket(mClientIp, mClientPort);

//从socket获取输入输出流
BufferedReader mClientIn = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
PrintWriter mClientOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mClientSocket.getOutputStream())), true);

//监听服务端下发的消息
String clientReceiverMessage;
if ((clientReceiverMessage = mClientIn.readLine()) != null) {
	if (mOnConnectListener != null) {
		mOnConnectListener.onMessage(clientReceiverMessage);
	}
} 

//给服务端发消息
mClientOut.println(mClientSendMessage);

代码封装Listener接口

在实际开发过程中,我们一般会把Socket这块封装起来,然后对外设置Listener接口,在其它模块里处理业务逻辑,也有的需要处理多个socket连接和通讯,

服务器端代码实现示例

public class TcpServer {

	private static final String TAG = "TcpServer";

	private static TcpServer mTcpServer = new TcpServer();
	private OnListener mOnListener;
	private ServerSocketThread mServerSocketThread;

	public static TcpServer getInstance() {
		return mTcpServer;
	}

	public void setOnListener(OnListener onListener) {
		mOnListener = onListener;
	}

	public interface OnListener {
		void onStart();

		void onNewClient(String serverIp, String clientIp, int count);

		void onError(Throwable e, String message);

		void onMessage(String ip, String message);

		void onAutoReplyMessage(String ip, String message);

		void onClientDisConnect(String ip);

		void onConnectTimeOut(String ip);
	}

	public void setPort(int port) {
		mServerPort = port;
	}
	
    ………………………………
    ………………………………
    ………………………………
}

十六进制收发处理

对接硬件的项目通讯协议有可能是用十六进制的,所以数据要在字符串\byte\int 十六进制转换,不过通讯部分本质一样,代码如下

  //十六进制 发送
  try {
      //byte[] msg = {(byte) 0xaa,(byte) 0xbb,(byte) 0x0d,(byte) 0x0a};
      byte[] msg = IntByteStringHexUtil.hexStrToByteArray("AABB0D0A");
      OutputStream socketWriter = socket.getOutputStream();

      socketWriter.write(msg);
  } catch (IOException e) {
      e.printStackTrace();
  }

  //十六进制 接收
  InputStream socketReader = socket.getInputStream();
  byte buf[] = new byte[1024];
  int len = socketReader.read(buf);

  byte data[] = new byte[len];
  System.arraycopy(buf, 0, data, 0, len);

  logClient(len+","+IntByteStringHexUtil.byteArrayToHexStr(data));

Demo源码下载地址

源码也都放在CSDN上了,有需要的可以借鉴

===> Android TCP Socket通信实例Demo源码Apk下载