打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
JavaSocket短连接实现分别接收字符串和16进制数据

做个笔记,在接收16进制数据的时候乱码了。原因是Socket在接收数据的时候需要根据不同的数据定义不同的接收方式,也就是约定好传输协议(具体体现在后面服务端接收16进制那里)。

字符串的发送接收

字符串发送:

字符串接收:

客户端代码:

没什么好说的,复制粘贴导包。

public static void main(String[] args)    {        try        {            Socket socket = new Socket("localhost", 8888);            //得到一个输出流,用于向服务器发送数据            OutputStream outputStream = socket.getOutputStream();            //将写入的字符编码成字节后写入一个字节流            OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8");            System.out.println("请输入数据:");            while (true)            {				Scanner sc = new Scanner(System.in);                String data = sc.nextLine();                writer.write(data);                //刷新缓冲                writer.flush();                //只关闭输出流而不关闭连接                socket.shutdownOutput();                //获取服务器端的响应数据                //得到一个输入流,用于接收服务器响应的数据                InputStream inputStream = socket.getInputStream();                //字节流以UTF-8的编码转换为字符流                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");                //为输入流添加缓冲                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);                System.out.println("客户端IP地址:"   socket.getInetAddress().getHostAddress());                String info;                //输出服务器端响应数据                while ((info = bufferedReader.readLine()) != null)                {                    System.out.println("收到来自服务端的信息:"   info);                }                //关闭资源                bufferedReader.close();                inputStreamReader.close();                inputStream.close();                writer.close();                outputStream.close();                socket.close();            }        }        catch (IOException e)        {            e.printStackTrace();        }    }

服务端代码:

注意readLine()方法,客户端发送的内容结尾一定要有换行符,不然会一直阻塞导致客户端得不到响应。其它注释里都有。

try        {            System.out.println(">>>服务启动,等待终端的连接\n");            ServerSocket server = new ServerSocket(8888);            int count = 0;            while (true)            {                //开启监听                Socket socket = server.accept();                count  ;                System.out.println(">>>第"   count   "个终端连接成功");                ServerThread thread = new ServerThread(socket);                thread.start();            }        }        catch (IOException e)        {            e.printStackTrace();        }
/** * 短连接 */public class ServerThread extends Thread{    private Socket m_socket;    public ServerThread(Socket socket)    {        this.m_socket = socket;    }    @Override    public void run()    {        //字节输入流        InputStream inputStream = null;        //字节输出流        OutputStream outputStream = null;        //字节输入流到字符输入流的转换        InputStreamReader inputStreamReader = null;        //加快字符读取速度        BufferedReader bufferedReader = null;        //打印输出流        PrintWriter printWriter = null;        try        {            inputStream = m_socket.getInputStream();            String info;            inputStreamReader = new InputStreamReader(inputStream);            bufferedReader = new BufferedReader(inputStreamReader);            //注意,readLine()方法如果没有读到报文结束符(换行)会一直阻塞            while ((info = bufferedReader.readLine()) != null)            {                System.out.println(">>>线程"   this.getId()   "收到来自终端的信息:"   info);            }            //关闭终端的输入流(不关闭服务端的输出流),此时m_socket虽然没有关闭,但是客户端已经不能再发送消息            m_socket.shutdownInput();            //解析终端的信息            String responseStr = "Null...";            if (null != info && !"".equals(info))            {                //模拟业务处理Thread.sleep(10000);                responseStr = new MessageReceive().RecevieHexStr(info);            }            outputStream = m_socket.getOutputStream();            printWriter = new PrintWriter(outputStream);            printWriter.write(responseStr);            printWriter.flush();        }        catch (Exception e)        {            e.printStackTrace();        }        //关闭资源        finally        {            System.out.println(">>>本次连接已断开\n");            try            {                if (printWriter != null)                    printWriter.close();                if (outputStream != null)                    outputStream.close();                if (bufferedReader != null)                    bufferedReader.close();                if (inputStreamReader != null)                    inputStreamReader.close();                if (inputStream != null)                    inputStream.close();                if (m_socket != null)                    m_socket.close();            }            catch (IOException e)            {                e.printStackTrace();            }        }    }}

 16进制数据的发送接收

客户端代码:无

由Socket测试工具来完成,网上大把,自行下载。

服务端代码:

开头说过使用Socket通信需要约定好协议,否则服务端不知道你客户端内容是否发送完毕,就会一直阻塞。前面的字符串的发送和接收其实也是有协议存在的,这个协议就是字符串和换行符,服务端读取的时候将字节流转为字符流,然后一行行的读取,读到换行符的时候就表示客户端的消息已发送完毕。

但是当客户端发送的是16进制数据的时候,这个时候服务端仍然用读取字符串的方式去处理就会乱码。所以这里采用的方法是将字节流以字节的形式一个一个的读出来,然后每个字节转为16进制的字符串。

byte[] bytes = new byte[1];while ((dataInputStream.read(bytes)) != -1)    String tempStr = ConvertUtil.ByteArrayToHexStr(bytes);

同理,也需要一个标识符表示客户端的内容已经发送完毕,否则read()方法也会一直阻塞,导致客户端得不到响应。比如客户端发送内容的末尾加个7E,当服务端读到7E就跳出While循环,但前提是要保证发送内容里面7E是唯一的,如果有其它需要用7E表示的自行转义,然后服务端读取完内容以后再转义回来。

这里我使用的是另外一种方法判断客户端的内容是否发送完毕:InputStream对象的available()方法。

dataInputStream.available()

官方解释:返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。下一个调用可能是同一个线程,也可能是另一个线程。一次读取或跳过此估计数个字节不会受阻塞,但读取或跳过的字节数可能小于该数。大白话就是:返回剩余未读长度

至于其它的注释里都有写

/** * 短连接 */public class ServerThread extends Thread{    private Socket m_socket;    public ServerThread(Socket socket)    {        this.m_socket = socket;    }    @Override    public void run()    {        //字节输入流        InputStream inputStream = null;        //字节输出流        OutputStream outputStream = null;        //缓冲输入流        BufferedInputStream bufferedInputStream = null;        //数据输入流        DataInputStream dataInputStream = null;        //打印输出流        PrintWriter printWriter = null;        try        {            inputStream = m_socket.getInputStream();            String info = "";            bufferedInputStream = new BufferedInputStream(inputStream);            dataInputStream = new DataInputStream(bufferedInputStream);            //一次读取一个byte            byte[] bytes = new byte[1];            //注意,read()方法如果没有数据会一直阻塞,也就是永远不会等于-1,除非客户端调用close(),如果想在while循环外部获取数据则需要设定跳出条件            while ((dataInputStream.read(bytes)) != -1)            {                String tempStr = ConvertUtil.ByteArrayToHexStr(bytes)   " ";                info  = tempStr;                //返回下次调用可以不受阻塞地从此流读取或跳过的估计字节数,如果等于0则表示已经读完                if (dataInputStream.available() == 0)                {                    System.out.println(">>>终端信息读取完毕,最后一位:"   tempStr);                    break;                }            }            System.out.println(">>>线程"   this.getId()   "收到来自终端的信息:"   info);            //关闭终端的输入流(不关闭服务端的输出流),此时m_socket虽然没有关闭,但是客户端已经不能再发送消息            m_socket.shutdownInput();            //解析终端的信息            String responseStr = "Null...";            //模拟业务处理            Thread.sleep(10000);            outputStream = m_socket.getOutputStream();            printWriter = new PrintWriter(outputStream);            printWriter.write(responseStr);            printWriter.flush();        }        catch (Exception e)        {            e.printStackTrace();        }        //关闭资源        finally        {            System.out.println(">>>本次连接已断开\n");            try            {                if (printWriter != null)                    printWriter.close();                if (outputStream != null)                    outputStream.close();                if (inputStream != null)                    inputStream.close();                if (bufferedInputStream != null)                    bufferedInputStream.close();                if (dataInputStream != null)                    dataInputStream.close();                if (m_socket != null)                    m_socket.close();            }            catch (IOException e)            {                e.printStackTrace();            }        }    }}
自定义的转换类:
/**     * 普通byte[]转16进制Str     *     * @param array     */    public static String ByteArrayToHexStr(byte[] array)    {        StringBuilder stringBuilder = new StringBuilder();        for (int i = 0; i < array.length; i  )        {            String hex = Integer.toHexString(array[i] & 0xFF);            if (hex.length() == 1)            {                stringBuilder.append("0");            }            stringBuilder.append(hex);        }        return stringBuilder.toString();    }

 

来源:https://www.icode9.com/content-1-373801.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
原来BufferedReader不能和InputStream交替使用
用Socket做一个通讯项目的一点心得
基于Tcp协议的简单Socket通信实例(JAVA)
Java实现简单的Socket服务器与客户端字符串通讯(适合初学者阅读)
JAVA:IO流 之 节点流与处理流(2)
实现server和client模型程序
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服