由一个TCP程序引出线程之间的区别与运用-基于Spring Boot

18 篇文章 0 订阅

考完研闲来没事做,着手写一个TCP通信程序。也顺便复习了以下java中三种线程之间的区别与运用。

主要功能:能够实现TCP数据的接收与转发,并且可以通过同样的restful接口实现TCP中socket调用(通过唯一标识符deviceCode实现socket的绑定)

1、继承Thread类;

2、实现Runnable接口;(callback不做另外的解析)

大家在辨识Thread与Runnable很多还在extend与implement关键字之间的区别,Thread其实是实现了Runnable函数的,但是在具体的运用上,是由很大的区别。

通过继承Thread创建线程是不会阻塞主线程的后续执行的,尤其是在serverSocket.appect()方法的使用上,由于appect方法是阻塞的,所以在接收到连接的时候我们应该是使用继承thread的线程而非实现runable接口。

源码:https://github.com/AbitGo/mybatis_csdn/tree/master/TCPServer

首先来看实验现象

 如果需要使用特定设备下发需要在发送之前绑定socket,就是第一次发送tcp数据格式需要进行数据绑定(下图即可

使用postman进行命令下发

以下为代码(基于Spring Boot的)

SocketParam.java
package com.bl.utli;

import com.bl.demo.subSocketClient;

import java.net.Socket;
import java.util.HashMap;

/**
 * @author 韦海涛
 * @version 1.0
 * @date 2021/2/1 20:12
 */
public class SocketParam {
    public static HashMap<String, subSocketClient> DeviceCode2SocketMap = new HashMap<>();
    public static int PortNum = 7880;
    public static String TypeRegister = "01";
    public static String TypeUpdateData = "02";
    public static String SendSuccess = "OK";
    public static String SendError = "ERROR";
}
TCPServer.java
package com.bl.demo;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.*;

import static com.bl.utli.SocketParam.*;

public class TCPServer extends Thread {
    ServerSocket serverSocket = null;
    public static TCPServer tcpServer;

    @PostConstruct
    public void init(){
        tcpServer = this;
        tcpServer.start();
    }

    public String socketSendData(String deviceCode,String sendData){
        //不为空时
        subSocketClient temp = DeviceCode2SocketMap.get(deviceCode);
        if(null!=temp){
            return temp.sendSocketData(sendData,deviceCode);
        }else{
            return SendError;
        }
    }

    @Override
    public void run() {
        try {
            serverSocket = new ServerSocket(PortNum);
        } catch (IOException e) {
            System.out.println("the port cannot open.");
        }
        while(true){
            try {
                System.out.println("wait. .. ...");
                //使用accept()是阻塞方法
                Socket socketTemp = serverSocket.accept();
                new subSocketClient(this.serverSocket,socketTemp).start();
                //为每个连接都创建一个线程客户端
            } catch (IOException e) {
                System.out.println("happening");
            }
        }
    }
}
subSocketClient.java
package com.bl.demo;

import com.alibaba.fastjson.JSONObject;

import javax.websocket.SendResult;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

import static com.bl.utli.SocketParam.*;

/**
 * @author 韦海涛
 * @version 1.0
 * @date 2021/2/1 20:53
 */
public class subSocketClient extends Thread {
    private ServerSocket serverSocket;
    private Socket socket;

    public subSocketClient(ServerSocket serverSocket, Socket socket) {
        this.serverSocket = serverSocket;
        this.socket = socket;
    }

    public String sendSocketData(String sendData,String deviceCode){
        try {
            BufferedReader br = null;
            PrintWriter pw = null;
            br = new BufferedReader(new InputStreamReader(System.in));
            pw = new PrintWriter(socket.getOutputStream(), true);
            //查看socket是否存在
            if (!socket.isClosed()) {
                pw.println(sendData);
                pw.flush();
                return SendSuccess;
            }else {
                //不存在则移除该socket
                DeviceCode2SocketMap.remove(deviceCode);
                return SendError;
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        return SendError;

    }

    @Override
    public void run() {
        try {
            //获取输入流
            InputStream inputStream = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            byte[] buf = new byte[1024];
            //接收数据
            int line = 0;
            while ((line = inputStream.read(buf)) != -1) {
                String param = new String(buf, 0, line);
                JSONObject jsonObject = JSONObject.parseObject(param);

                String type = jsonObject.getString("type");
                if(type.equals(TypeRegister)){
                    String deviceCode = jsonObject.getString("deviceCode");
                    DeviceCode2SocketMap.put(deviceCode,this);
                    //sendSocketData("OK",deviceCode);//测试
                }
                else if(type.equals(TypeUpdateData)){
                    String deviceCode = jsonObject.getString("deviceCode");
                    //这边方式存放数据
                    String deviceData = jsonObject.getString("deviceData");
                }

            }

            //线程停止10ms
            Thread.sleep(10);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 控制.java

package com.bl.demo;
import com.alibaba.fastjson.JSONObject;
import com.bl.utli.PubicMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import static com.bl.demo.TCPServer.tcpServer;
import static com.bl.utli.SocketParam.SendError;
import static com.bl.utli.SocketParam.SendSuccess;


@RestController
public class TotolController {
    @RequestMapping(value = "/Device/PostCommand", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @CrossOrigin
    public String PostCommand(@RequestBody String GetJson) throws Exception {
        JSONObject getJson = JSONObject.parseObject(GetJson);
        String deviceCode = getJson.getString("deviceCode");
        String sendData = getJson.getString("sendData");
        String result = tcpServer.socketSendData(deviceCode,sendData);
        if(result.equals(SendSuccess)){
            return "下发成功";
        }else if(result.equals(SendError)){
            return "下发失败";
        }
        return "下发失败";
    }

    @RequestMapping(value = "/Device/Test", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @CrossOrigin
    public String Test() throws Exception {

        return "OK";
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值