Android TCP/IP网络编程Socket通信实现Demo(附源码)

本文主要讲解安卓(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和端口然后建立或者连接。


在这里插入图片描述

image

Demo演示及实现

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


tcpdemo.gif

一、权限

 <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下载

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容