我感觉,简单的tcp通信网上应该容易搜到,但对tcp加密,以及tcp当做http通信和接收推送时,就会有冲突吧。
最后我封装了它 。
这是tcp 部分:
/** * Created by zhu on 2017/11/16. */ public class MyService extends Service {//Service 的生命周期 private static MyService _instance; /** * ----------------TCPClient------------------------ */ private Timer timer; private TimerTask task; private boolean isRevFromServer; private Socket clicksSocket = null; private boolean activi_destroy;//activity有没有销毁 private DataInputStream dataInputStream; /** * ----------------TCPClient------------------------ */ @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); _instance = this; } /** * * @return */ public static MyService getInstance(){ return _instance; } /** * ----------------TCPClient------------------------ */ /** * 连接Tcp */ public void connectTCP(String wangguan_ip,final ICallback icallback ,final IConnectTcpback iconnect) { initSocket(wangguan_ip,icallback,iconnect); } /** * socket初始化 */ private void initSocket(String wangguan_ip,final ICallback icallback ,final IConnectTcpback iconnect) { clicksSocket = null; try { // clicksSocket= new Socket("192.168.169.134", 8080); clicksSocket = new Socket(); SocketAddress socAddress = new InetSocketAddress(wangguan_ip, 32678);//wangguan_ip,32678 //TcpServer 端口 32678 clicksSocket.connect(socAddress, 10000);//此处超时间为20s isRevFromServer = true;//说明已经连接到服务器端Socket,不需要在用心跳定时器 // clicksSocket.setSoTimeout(5000); clicksSocket.sendUrgentData(0xFF);//发送1个字节的紧急数据,默认情况下,服务器端没有开启紧急数据处理,不影响正常通信 // Receivetuisong_Thread receive_thread = new Receivetuisong_Thread(clicksSocket, "command",icallback);//创建客户端处理线程对象 // Thread t = new Thread(receive_thread);//创建客户端处理线程 // // // Message message = Message.obtain(); // message.obj = "sraum_verifySocket"; // hand_tcp_client_send.sendMessage(message); //连接tcp成功 if (iconnect != null) iconnect.process(); // // t.start();//启动线程 //启动接收线程 } catch (IOException e) {//连接超时异常,重新去连接30分钟e.printStackTrace();//如果服务器端没有连,客户端超过3min,就会抛出异常 //开启心跳每个3min,去连接 isRevFromServer = false;//连接服务器端超时,开启定时器 // isServerClose(clicksSocket); } } /** * tcp_socket发送数据 */ /** * 连接成功,去认证有效的TCP链接 (APP -》网关) * * @param */ public void sraum_send_tcp(final Map map, final String command_send, final ICallback icallback) { new Thread(new Runnable() { @Override public void run() { Receive_Thread receive_thread = new Receive_Thread(clicksSocket, command_send,icallback);//创建客户端处理线程对象 Thread t = new Thread(receive_thread);//创建客户端处理线程 t.start(); // list_recev_tcp.add(receive_thread); String json_str = new Gson().toJson(map); try { // String aes_str = Encrypt(json_str,"masskysraum-6206"); //0a4ab23ad13aac565069283aac3882e5 //在这里解析二维码,变成房号 // 密钥 String key = "masskysraum-6206";//masskysraum-6206 // 解密 String DeString = null; try { // content = "0a4ab23ad13aac565069283aac3882e5"; DeString = Encrypt(json_str,key); } catch (Exception e) { e.printStackTrace(); } send_tcp_socket(DeString);//send tcpclient socket } catch (Exception e) { e.printStackTrace(); } } }).start(); } /** * 发送tcpSocket数据流 */ public void send_tcp_socket(String tcp_client_content) { //获取输出流 OutputStream outputStream = null; try { if (clicksSocket != null) outputStream = clicksSocket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } //发送数据 try { if (outputStream != null) outputStream.write(tcp_client_content.getBytes()); } catch (IOException e) { e.printStackTrace(); } } }
这是tcp调用的一部分:
MyService.getInstance().connectTCP(user.ip, new ICallback() { @Override public void process(Object map) { } @Override public void error(String data) { //长连接异常 } }, new IConnectTcpback() {//连接tcpServer成功 @Override public void process() { runOnUiThread(new Runnable() { @Override public void run() { ToastUtil.showToast(Main_New_Activity.this, "连接TCPServer成功"); } }); } }); } }).start(); }
上面是把tcp当做http通信使用的;接收部分用单独的线程。即收发一次线程被kill。
保持长连接的话,即接收实时推送;接收线程要一直存在。
这是客户端socket接收线程部分:
/** * * 接收线程 * */ public class Receive_Thread implements Runnable//实现Runnable { private Socket clientSocket; private InputStream inputStream; //客户端接收子线程标志位,它的生命周期随着客户端物理连接断开,或者3min心跳后,客户端 public Boolean Recev_flag; private String command; private DataInputStream input; private ICallback iCallback; //虽然连接,单3min之后依然没响应,要关掉该客户端子线程 public Receive_Thread(final Socket clientSocket, String command, ICallback icallback) { this.clientSocket = clientSocket; this.Recev_flag = true; this.iCallback = icallback; try { InputStream inputStream = clientSocket.getInputStream(); this.inputStream = inputStream; input = new DataInputStream(inputStream); // dataInputStream = input; this.command = command; }catch (Exception ex) { } } @Override public void run() { byte[] b = new byte[1024];//new byte[10000]; while(Recev_flag) { int length = 0; try { length = input.read(b); if (length == -1) {//当服务器端断开时,input.read(b)就会返回 -1,//开启心跳包每个3min 去连接, Recev_flag = false;//杀死该线程,然后 // String ip = (String) SharedPreferencesUtil.getData(MainActivity.this, "ip", ""); // initSocket(ip);//tcp客户端主动连接tcpServer有20s的超时时间 //遍历子线程list,删除该子接收线程Item项 iCallback.error(""); } else { final String Msg = new String(b, 0, length); //byte转换为字符串 // final String Msg = ByteUtils.bytesToHexString(b,length); // runOnUiThread(new Runnable() { // @Override // public void run() { txt_show.setText(txt_show.getText() + Msg); // } // }); Log.v("data", Msg); if (command.equals("command")) {//保持长连接,接收推送消息 } else { Map map = new HashMap(); map.put("command", command); // 密钥 String key = "masskysraum-6206";//masskysraum-6206 // 解密 String DeString = null; try { // content = "0a4ab23ad13aac565069283aac3882e5"; DeString = Decrypt(Msg, key); Log.e("robin debug","DeString:" + DeString); } catch (Exception e) { e.printStackTrace(); } map.put("content_tcp_rev", DeString); // hand_tcp_client_rev.sendMessage(message); Recev_flag = false;//杀死该线程,然后 iCallback.process(map); } } } catch (IOException e) { e.printStackTrace(); } } } }