安卓Socket处理

初学Android Socket 部分代码参考于网络,结合项目测试后修改总结,在此记录。




1
/** 2 * <p> 3 * socket连接服务 4 */ 5 public class SocketService extends Service { 6 7 private static final String TAG = "SocketService"; 8 9 /*socket*/ 10 private Socket socket; 11 /*连接线程*/ 12 private Thread connectThread; 13 private Timer timer = new Timer(); 14 15 16 /* 读写输入流*/ 17 private InputStream inputStream; 18 private DataInputStream dis; 19 20 /*读接收数据线程*/ 21 private Thread readThread; 22 /*接收数据长度*/ 23 private int rcvLength; 24 /*接收数据*/ 25 private String rcvMsg; 26 /* 读取保存进数组*/ 27 byte buff[] = new byte[1024 * 1024 * 2]; 28 29 private OutputStream outputStream; 30 31 32 private SocketBinder sockerBinder = new SocketBinder(); 33 private String ip;//IP地址,这里最好单独建立一个存放数据类,用来存放网络通讯使用到的数据 34 private String port;//端口号 35 private TimerTask task; 36 37 /*默认重连*/ 38 private boolean isReConnect = true; 39 40 41 /* 线程状态,安全结束线程*/ 42 private boolean threadStatus = false; 43 44 private Handler handler = new Handler(Looper.getMainLooper()); 45 46 47 @Override 48 public IBinder onBind(Intent intent) { 49 return sockerBinder; 50 } 51 52 53 public class SocketBinder extends Binder {//通过ServiceConnection获取,后面会讲解 54 /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService */ 55 public SocketService getService() { 56 return SocketService.this; 57 } 58 } 59 60 @Override 61 public void onCreate() { 62 super.onCreate(); 63 } 64 65 66 @Override 67 public int onStartCommand(Intent intent, int flags, int startId) { 68 69 /*拿到传递过来的ip和端口号*/ 70 ip = Constants.INTENT_IP; 71 port = Constants.INTENT_PORT; 72 73 Log.e(TAG, "000" + DeviceUuidFactory.getUuid()); 74 75 /*初始化socket*/ 76 initSocket(); 77 78 return super.onStartCommand(intent, flags, startId); 79 } 80 81 82 /*初始化socket*/ 83 private void initSocket() { 84 85 if (socket == null && connectThread == null) { 86 87 //启动读取数据 88 connectThread = new Thread(new Runnable() { 89 @Override 90 public void run() { 91 socket = new Socket(); 92 try { 93 /*超时时间为20秒*/ 94 socket.connect(new InetSocketAddress(ip, Integer.valueOf(port)), 20000); 95 /*连接成功的话 发送心跳包*/ 96 if (socket.isConnected()) { 97 98 inputStream = socket.getInputStream(); 99 dis = new DataInputStream(inputStream); 100 101 if (inputStream != null) { 102 /* 开启读写线程 */ 103 threadStatus = true; 104 readThread = new ReadThread(); 105 readThread.start(); 106 } 107 108 /*因为Toast是要运行在主线程的 这里是子线程 所以需要到主线程哪里去显示toast*/ 109 // toastMsg("socket已连接111111111"); 110 111 /*发送心跳数据*/ 112 sendBeatData(); 113 } 114 115 } catch (IOException e) { 116 e.printStackTrace(); 117 if (e instanceof SocketTimeoutException) { 118 toastMsg("连接超时,正在重连"); 119 releaseSocket(); 120 } else if (e instanceof NoRouteToHostException) { 121 toastMsg("该地址不存在,请检查"); 122 stopSelf(); 123 } else if (e instanceof ConnectException) { 124 toastMsg("连接异常或被拒绝,请检查"); 125 stopSelf(); 126 } 127 } 128 } 129 }); 130 /*启动连接线程*/ 131 connectThread.start(); 132 } 133 } 134 135 /*因为Toast是要运行在主线程的 所以需要到主线程哪里去显示toast*/ 136 private void toastMsg(final String msg) { 137 138 handler.post(new Runnable() { 139 @Override 140 public void run() { 141 Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); 142 } 143 }); 144 } 145 146 147 /** 148 * @param order 149 * @param msg//测试时使用 150 */ 151 /*发送数据*/ 152 public void sendOrder(final String order, final String msg) { 153 if (socket != null && socket.isConnected()) { 154 /*发送指令*/ 155 new Thread(new Runnable() { 156 @Override 157 public void run() { 158 try { 159 Log.e("准备回复消息:", msg); 160 outputStream = socket.getOutputStream(); 161 if (outputStream != null) { 162 outputStream.write(order.getBytes("gbk")); 163 outputStream.flush(); 164 Log.e("消息发送成功:", order); 165 } 166 } catch (IOException e) { 167 e.printStackTrace(); 168 //releaseSocket(); 169 Log.e("消息回复异常", msg); 170 } 171 } 172 }).start(); 173 } else { 174 Log.e(TAG, "socket连接错误,请重试"); 175 releaseSocket(); 176 } 177 } 178 179 180 /** 181 * 发送连接状态消息 182 * 183 * @param constants 184 */ 185 private void sendEventMsg(String constants) { 186 EventMsg msg = new EventMsg(); 187 msg.setTag(constants); 188 EventBus.getDefault().post(msg); 189 } 190 191 /** 192 * 发送连接状态消息 193 * 194 * @param constants 195 */ 196 private void sendEventMsg(String constants, String rcvMsg) { 197 EventMsg msg = new EventMsg();//EventMsg的使用自行百度 198 msg.setTag(constants); 199 msg.setMsg(rcvMsg); 200 EventBus.getDefault().post(msg); 201 } 202 203 204 /** 205 * 接收数据 206 */ 207 private class ReadThread extends Thread { 208 @TargetApi(Build.VERSION_CODES.KITKAT) 209 @Override 210 public void run() { 211 super.run(); 212 //判断进程是否在运行,更安全的结束进程 213 try { 214 while (!socket.isClosed() && threadStatus && ((rcvLength = dis.read(buff)) != -1)) { 215 216 Log.e(TAG, "buff:" + buff); 217 218 if (rcvLength > 0) { 219 rcvMsg = new String(buff, 0, rcvLength, "GBK"); 220 toastMsg("收到服务器消息"); 221 //接收到数据 222 handleData(rcvMsg);//处理数据并回复服务器 223 } 224 } 225 } catch (Exception e) { 226 toastMsg("接收总控数据异常"); 227 } 228 229 } 230 } 231 232 233 /*定时发送数据*/ 234 private void sendBeatData() { 235 if (timer == null) { 236 timer = new Timer(); 237 } 238 239 if (task == null) { 240 task = new TimerTask() { 241 @Override 242 public void run() { 243 try { 244 outputStream = socket.getOutputStream(); 245 /*这里的编码方式根据需求去改*/ 246 outputStream.write("这是一条心跳数据".getBytes("gbk")); 247 outputStream.flush(); 248 /*发送连接成功的消息*/ 249 //这里可以建立一条消息发送到Activity处理界面相关 250 } catch (Exception e) { 251 /*发送失败说明socket断开了或者出现了其他错误*/ 252 toastMsg("连接断开,正在重连"); 253 /*发送连接失败的消息*/ 254 sendEventMsg(Constants.CONNET_FAIL, ""); 255 /*重连*/ 256 releaseSocket(); 257 e.printStackTrace(); 258 } 259 } 260 }; 261 } 262 263 timer.schedule(task, 0, 60000);//心跳每隔60000毫秒发送一次,60s 264 } 265 266 267 /*释放资源*/ 268 private void releaseSocket() { 269 270 if (task != null) { 271 task.cancel(); 272 task = null; 273 } 274 if (timer != null) { 275 timer.purge(); 276 timer.cancel(); 277 timer = null; 278 } 279 280 if (outputStream != null) { 281 try { 282 outputStream.close(); 283 284 } catch (IOException e) { 285 e.printStackTrace(); 286 } 287 outputStream = null; 288 } 289 290 if (socket != null) { 291 try { 292 socket.close(); 293 294 } catch (IOException e) { 295 } 296 socket = null; 297 } 298 299 if (connectThread != null) { 300 connectThread = null; 301 } 302 303 if (readThread != null) { 304 readThread = null; 305 } 306 307 /*重新初始化socket*/ 308 if (isReConnect) { 309 initSocket(); 310 } 311 312 } 313 314 315 /** 316 * 服务器消息回复 317 * 318 * @param msg 319 * @param 320 */ 321 @TargetApi(Build.VERSION_CODES.KITKAT) 322 public void handleData(String msg) throws IOException { 323 sendOrder("确认收到消息", msg); 324 } 325 326 327 @Override 328 public void onDestroy() { 329 super.onDestroy(); 330 Log.i("SocketService", "onDestroy"); 331 isReConnect = false; 332 threadStatus = false; 333 releaseSocket(); 334 } 335 }

IBinder 使用方法
 1  ServiceConnection serviceConnection = new ServiceConnection() {
 2                              @Override
 3                              public void onServiceConnected(ComponentName name, IBinder service) {
 4                                  SocketService.SocketBinder socketBinder = (SocketService.SocketBinder) service;
 5                                  socketBinder.getService().
 6                              }
 7  
 8                              @Override
 9                              public void onServiceDisconnected(ComponentName name) {
10 
11                             }
12                         };

 

 


 

posted @ 2019-04-24 12:16  bbqopdd  阅读(363)  评论(0编辑  收藏  举报