WEBSOCKET简单使用

作为开发一年的工程师来说这是我最顺利的一次开发。

为何呢?

因为当时开发已经有段时间了,所以思路很清晰。给了我一个web socket,大概也就用了一天就写完了。虽然说写的并不是那么完美。(对web socket的封装神的没做直接写)

首先呢我先说一下。socket技术有长连接和长轮询两种写法(比我牛逼的别来打我脸,但是欢迎告诉我哪里不对)。

长连接个人通俗的讲就是和服务器的链接不断开,并且能正常的传输信息。

长轮询就是隔一段时间断开与服务器的链接,再重新连接。(不是闲的啊,你想先几十万几百万人同时在线的情况,那服务器的压力就);

我在项目中使用的就是长连接技术。

怎么写的呢请看:

package com.chihuobao.app.base.client;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Timer;
import java.util.TimerTask;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;

import com.alibaba.fastjson.JSONObject;
import com.chihuobao.app.base.log.FrameLog;
import com.chihuobao.app.base.utils.PrefsConfig;
import com.chihuobao.app.itstack.netty.common.ModelAction;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

public class MessageService extends Service {
	private String shopid = PrefsConfig.ShopId;// 获取本地Shopid
	private MessageClient messageClient;
	public int timer = 0, ts = 0;
	private boolean isLoop = true;
	private boolean isCallHead = false;//作用 心跳处理
	private Timer timerl;//作用 重连线程
	private TimerTask timerTask;
	private Handler mHandler = new Handler(new Handler.Callback() {

		@Override
		public boolean handleMessage(Message arg0) {
			timerl = new Timer(true);
			switch (arg0.what) {
			case 91:
				timerTask = new TimerTask() {
					@Override
					public void run() {
						Message msg = new Message();
						msg.what = 31;
						FrameLog.e("计时器", timer + "");
						mHandler.sendMessage(msg);

					}
				};
				timerl.schedule(timerTask, 0, 8000);// 0s后执行 每3秒执行一次
				break;
			case 31:

				if (messageClient != null) {
					if (messageClient.isOpen()) {
						messageClient.close();//主动关闭上一次长链接
					}
					messageClient = null;
				}
				System.out.println("开始重新连接");
				getExampleClient();
				break;
			default:
				break;
			}

			return false;
		}
	});

	public int onStartCommand(Intent intent, int flags, int startId) {
		getExampleClient();//初始化长连接   
		looperHead();//开启心跳线程

		return START_STICKY;
	};
    //实例化长链接客户端
	private void getExampleClient() {
		new Thread() {
			public void run() {
				System.out.println("开始连接");
				try {

//					 messageClient = new MessageClient(new URI(
//					 "ws://192.168.99.113:9876"));
					messageClient.connectBlocking();//链接服务器长链接

				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (URISyntaxException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			};

		}.start();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		if (messageClient != null) {
				if (messageClient.isOpen()) {
					messageClient.close();//主动关闭上一次长链接
				}
				messageClient = null;
		}
		// onCreate();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	// 写的不太好的心跳包
	public void looperHead() {
		Thread headThread = new Thread() {
			@SuppressWarnings("static-access")
			public void run() {

				while (true) {
					if (isCallHead == true && messageClient != null
							&& !messageClient.isClosed()
							&& !messageClient.isFlushAndClose()) {
						if (timer == 15) {
							System.out.println("心跳包");
                               if (messageClient.isOpen()) {
       							  messageClient.send("&HEAT0053\n\n");//发送心跳包
							}
						}
						if (timer > 25) {
							System.out.println("断开连接");//主动断开
							if (messageClient != null) {
								if (messageClient.isOpen()) {
									System.out.println("断开连接");
									messageClient.close();//执行关闭方法
								} 
							}
							putService();
						} 
						try {
							Thread.sleep(1000);//1S增加一次计数器
							timer = timer + 1;
							
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}

			};
		};
		headThread.start();
	}
//接受扫码的服务器推送
	class MessageClient extends WebSocketClient {
		private String mkey = null;

		public MessageClient(URI serverUri, Draft draft) {
			super(serverUri, draft);
		}

		public MessageClient(URI serverURI) {
			super(serverURI);
		}

		@Override
		public void onOpen(ServerHandshake handshakedata) {
			System.out.println("连接完成");
			timer = 0;// 初始化心跳包计数器
			isCallHead = true;// 通知关闭方法可以放松消息
			isLoop = true;// 开启心跳循环
			if (timerTask != null) {
				System.out.println("开始停止计时");
				timerTask.cancel();// 关闭重连计数器执行线程
				timerl.cancel();// 关闭重连计数器
			}
		}

		@Override
		public void onMessage(String message) {//接收到服务器的推送消息
			FrameLog.e("接受到服务器的信息1", message + "\n" + message.length());
			String temp = null;
			if (message != null) {
				if (message.length() == 4) {
					temp = message.substring(0, 4);
					FrameLog.e("接受到服务器的信息", "temp=" + "心跳包" + temp);
					if (temp.equals("HEAT")) {
						timer = 0;
						FrameLog.e("接受到服务器的信息", "temp=" + "心跳包");
					}
				} 
				}
				message = null;
			}
		}


		@Override
		public void onFragment(Framedata fragment) {
			System.out.println("received fragment: "
					+ new String(fragment.getPayloadData().array()));
		}

		@Override
		public void onClose(int code, String reason, boolean remote) {//检测到关闭链接的方法
			// The codecodes are documented in class
			// org.java_websocket.framing.CloseFrame
			System.out.println("Connection closed by 执行关闭方法");
			if (isLoop == true) {
				putService();// 开启重连线程
			}
		}

		@Override
		public void onError(Exception ex) {
			ex.printStackTrace();
		}

		private boolean getMsg(String json) {
			JSONObject jsonObject = JSONObject.parseObject(json);
			String result = jsonObject.getString("result");
			System.out.println("解析数据错误提示**********************" + json);
			if (result.equals("success")) {
				return true;
			} else {
				return false;
			}

		}

	

	}
	private void putService() {//发送重连信息
		Message message = new Message();
		message.what = 91;// 重连消息
		isCallHead = false;// 关闭心跳包
		isLoop = false;// 关闭重连复发
		if (mHandler != null) {
			mHandler.sendMessage(message);
		}
	}
}

大家发现没我喜欢用Handler而不是timer因为我习惯了这么写了,当然websocket有它自己的timer大家可以用哪个。

这里说几个地方。

没用网络开启,断开连接,网址不对,等等都会触发web socket的onClose方法,其实web socket也是对socket的一种封装,实质上也是socket。

心跳包要确定web socket在isOpen()的情况下close(),为什么不想connectBLOCKING方法一样用closeblocking()去关闭呢。你可以试试有时候关闭不上,特别是在断网的情况下。我猜可能是web socket封装了某些东西给close blocking导致有时候不能正常关闭,我会继续去查找资料确认下下。


这里说web socket的几个思想  第一是确认和服务器是否一直链接的心跳包。第二是短线之后重新链接。当别的activity开启这个service的时候大家会发现activity不会被回收,除非你清除进程。但是service会一直执行,所以要在activity的onDestroy()内把servicestop掉。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值