java-socket写一个tcp字节流通信的测试服务端

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

测试一个物联网设备,根据通讯协议进行测试
主要目的: 测试命令的正确性和设备的具体功能


提示:以下是本篇文章正文内容,下面案例可供参考

一、通讯方式

首先明确通讯方式:TCP 字节流
连接方式: 我们使用的网线,也可以使用RS485或者无线模块,网线最方便快捷、稳定且成本低
测试设备为客户端,我需要写一个服务端来进行交互通信
命令格式:十六进制数转字节流,字节流转十六进制数(帧格式采用CS校验)

二、具体实现

1.配置设备

吐槽一下:
厂家支持不是很友好,沟通效率差。
没有准确的说明书,最后才弄明白具体的操作和方案
在设备上配置好ip、端口、网关等网络配置

2.接收客户端的信息

接收客户端的消息,我首先使用了一个测试工具,发现设备一直有正常上报信息,才开始写的。也是确保设备能正常通讯。

明确自己是服务端、接收的信息为字节流
需要一直启动线程,确保可以一直接收到客户端传过来的信息
主动向客户端发送字节流

代码如下(示例):

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import org.json.JSONObject

public class ServerThread extends Thread {
    Socket socket = null;
    InetAddress inetAddress=null;//接收客户端的连接

    public ServerThread(Socket socket,InetAddress inetAddress) {
        this.socket = socket;
        this.inetAddress=inetAddress;
    }

    @Override
    public void run() {
    	new sendMessThread().start();//连接并返回socket后,再启用发送消息线程
        InputStream inputStream = null;//字节输入流
        InputStreamReader inputStreamReader = null;//将一个字节流中的字节解码成字符
        BufferedReader bufferedReader = null;//为输入流添加缓冲
        OutputStream outputStream = null;//字节输出流
        OutputStreamWriter writer = null;//将写入的字符编码成字节后写入一个字节流
        try {
        	//封装输入流(接收客户端的字节流)
            BufferedInputStream bis = new BufferedInputStream(
                    socket.getInputStream());
            DataInputStream dis = new DataInputStream(bis);
            byte[] bytes = new byte[1]; // 一次读取一个byte
            String ret = "";
            while (dis.read(bytes) != -1) {
                ret += bytesToHexString(bytes) + " ";
                if (dis.available() == 0) { //一个请求
                    System.out.println(socket.getRemoteSocketAddress() + ":" + ret);
                    ret = "";
                }
            }
            //这里定义的是原来接收json的
//          inputStream = socket.getInputStream();
//            inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
//            bufferedReader = new BufferedReader(inputStreamReader);
//            String info = null;//临时
//
//            //循环读取客户端信息
//            while ((info = bufferedReader.readLine()) != null) {
//                //获取客户端的ip地址及发送数据
//                System.out.println("服务器端接收:"+"{'from_client':'"+socket.getInetAddress().getHostAddress()+"','data':'"+info+"'}");
//            }
            
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            try {
                if (writer != null) {
                    writer.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    class sendMessThread extends Thread{
        @Override
        public void run(){
            super.run();
            Scanner scanner=null;
            OutputStream out = null;
            try{
                if(socket != null){
                    scanner = new Scanner(System.in);
                    out = socket.getOutputStream();
                    String in = "";
                    do {
                        in = scanner.next();
                        byte[] hex2Byte = hex2Byte(in.replace(" ", ""));
                        out.write(hex2Byte);
                        out.flush();//清空缓存区的内容
                    }while (!in.equals("q"));
                    scanner.close();
                    try{
                        out.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
    /**
     *  将16进制字符转换成byte[]数组。与byte2Hex功能相反。
     * @param string 16进制字符串
     * @return byte[]数组
     */
    public static byte[] hex2Byte(String string) {
        if (string == null || string.length() < 1) {
            return null;
        }
        // 因为一个byte生成两个字符,长度对应1:2,所以byte[]数组长度是字符串长度一半
        byte[] bytes = new byte[string.length() / 2];
        // 遍历byte[]数组,遍历次数是字符串长度一半
        for (int i = 0; i < string.length() / 2; i++) {
            // 截取没两个字符的前一个,将其转为int数值
            int high = Integer.parseInt(string.substring(i * 2, i * 2 + 1), 16);
            // 截取没两个字符的后一个,将其转为int数值
            int low = Integer.parseInt(string.substring(i * 2 + 1, i * 2 + 2), 16);
            // 高位字符对应的int值*16+低位的int值,强转成byte数值即可
            // 如dd,高位13*16+低位13=221(强转成byte二进制11011101,对应十进制-35)
            bytes[i] = (byte) (high * 16 + low);
        }
        return bytes;
    }
    /**
     * byte[]数组转换为16进制的字符串
     *
     * @param bytes 要转换的字节数组
     * @return 转换后的结果
     */
    public static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

}

代码如下(示例):

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;


public class SocketServer {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(1111);//创建绑定到特定端口的服务器Socket。
            Socket socket = null;//需要接收的客户端Socket
            int count = 0;//记录客户端数量
            System.out.println("服务器启动");
            //定义一个死循环,不停的接收客户端连接
            while (true) {
                socket = serverSocket.accept();//侦听并接受到此套接字的连接
               // new sendMessThread().start();//连接并返回socket后,再启用发送消息线程
                InetAddress inetAddress=socket.getInetAddress();//获取客户端的连接
                ServerThread thread=new ServerThread(socket,inetAddress);//自己创建的线程类
                thread.start();//启动线程
                count++;//如果正确建立连接
                System.out.println("客户端数量:" + count);//打印客户端数量
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

总结

测试用的内容,希望后面项目一切顺利
使用效果图:

在这里插入图片描述


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值