欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的Socket實(shí)現(xiàn)長(zhǎng)連接以及數(shù)據(jù)的發(fā)送和接收方式

 更新時(shí)間:2023年09月28日 10:14:42   作者:誰(shuí)把我名字用了!  
這篇文章主要介紹了Java的Socket實(shí)現(xiàn)長(zhǎng)連接以及數(shù)據(jù)的發(fā)送和接收方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Socket實(shí)現(xiàn)長(zhǎng)連接以及數(shù)據(jù)的發(fā)送和接收

既然是長(zhǎng)連接就免不了心跳檢測(cè),這里使用了一種比較簡(jiǎn)單的做法:服務(wù)端對(duì)當(dāng)前線程計(jì)時(shí),重要的話說(shuō)三遍,服務(wù)端、服務(wù)端、服務(wù)端!

如果超時(shí)沒(méi)有收到任何數(shù)據(jù)就關(guān)閉該線程對(duì)應(yīng)的Socket。

代碼復(fù)制粘貼即可運(yùn)行。

  • 發(fā)送時(shí):將String轉(zhuǎn)byte[]
  • 接收時(shí):將byte[]轉(zhuǎn)String

效果圖

客戶端代碼

 
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class SocketClient
{
    public static void main(String[] args)
    {
        try
        {
            Socket socket = new Socket("localhost", 8888);
            //得到一個(gè)輸出流,用于向服務(wù)器發(fā)送數(shù)據(jù)
            OutputStream outputStream = socket.getOutputStream();
            System.out.println("請(qǐng)輸入16進(jìn)制數(shù)據(jù):");
            Scanner sc = new Scanner(System.in);
            while (true)
            {
                String data = sc.nextLine();
                if ("exit".equals(data))
                {
                    return;
                }
                byte[] byteArray = HexStrToByteArray(data);
                outputStream.write(byteArray);
                //刷新緩沖
                outputStream.flush();
                //得到一個(gè)輸入流,用于接收服務(wù)器響應(yīng)的數(shù)據(jù)
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1]; // 一次讀取一個(gè)byte
                String info = "";
                while (true)
                {
                    if (inputStream.available() > 0)
                    {
                        inputStream.read(bytes);
                        String hexStr = ByteArrayToHexStr(bytes);
                        info += HexStrToStr(hexStr);
                        //已經(jīng)讀完
                        if (inputStream.available() == 0)
                        {
                            System.out.println("收到來(lái)自服務(wù)端的信息:" + info);
                            break;
                        }
                    }
                }
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    /**
     * 16進(jìn)制Str轉(zhuǎn)byte[]
     *
     * @param hexStr
     * @return
     */
    public static byte[] HexStrToByteArray(String hexStr)
    {
        if (hexStr == null)
        {
            return null;
        }
        if (hexStr.length() == 0)
        {
            return new byte[0];
        }
        byte[] byteArray = new byte[hexStr.length() / 2];
        for (int i = 0; i < byteArray.length; i++)
        {
            String subStr = hexStr.substring(2 * i, 2 * i + 2);
            byteArray[i] = ((byte) Integer.parseInt(subStr, 16));
        }
        return byteArray;
    }
    /**
     * byte[]轉(zhuǎn)16進(jìn)制Str
     *
     * @param byteArray
     */
    public static String ByteArrayToHexStr(byte[] byteArray)
    {
        if (byteArray == null)
        {
            return null;
        }
        char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[byteArray.length * 2];
        for (int i = 0; i < byteArray.length; i++)
        {
            int temp = byteArray[i] & 0xFF;
            hexChars[i * 2] = hexArray[temp >>> 4];
            hexChars[i * 2 + 1] = hexArray[temp & 0x0F];
        }
        return new String(hexChars);
    }
    /**
     * 16進(jìn)制的Str轉(zhuǎn)Str
     *
     * @param hexStr
     * @return
     */
    public static String HexStrToStr(String hexStr)
    {
        //能被16整除,肯定可以被2整除
        byte[] array = new byte[hexStr.length() / 2];
        try
        {
            for (int i = 0; i < array.length; i++)
            {
                array[i] = (byte) (0xff & Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16));
            }
            hexStr = new String(array, "UTF-8");
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return "";
        }
        return hexStr;
    }
}

服務(wù)端代碼

使用InputStream對(duì)象的available()方法判斷客戶端的內(nèi)容是否發(fā)送完畢

dataInputStream.available()

官方解釋:

返回此輸入流下一個(gè)方法調(diào)用可以不受阻塞地從此輸入流讀?。ɑ蛱^(guò))的估計(jì)字節(jié)數(shù)。

下一個(gè)調(diào)用可能是同一個(gè)線程,也可能是另一個(gè)線程。

一次讀取或跳過(guò)此估計(jì)數(shù)個(gè)字節(jié)不會(huì)受阻塞,但讀取或跳過(guò)的字節(jié)數(shù)可能小于該數(shù)。

用我的大白話就是:返回剩余未讀長(zhǎng)度

 
import java.io.*;
import java.net.Socket;
/**
 * 長(zhǎng)連接
 */
public class ServerThread extends Thread
{
    //16進(jìn)制數(shù)字字符集
    public static final String HEXSTRING = "0123456789ABCDEF";
    //心跳超時(shí)時(shí)間
    private static final int TIMEOUT = 60 * 1000;
    private Socket m_socket;
    //接收到數(shù)據(jù)的最新時(shí)間
    private long m_lastReceiveTime = System.currentTimeMillis();
    //該線程是否正在運(yùn)行
    private boolean m_isRuning = false;
    public ServerThread(Socket socket)
    {
        this.m_socket = socket;
    }
    @Override
    public void start()
    {
        if (m_isRuning)
        {
            System.out.println(">>>線程" + this.getId() + "啟動(dòng)失敗,該線程正在執(zhí)行");
            return;
        }
        else
        {
            m_isRuning = true;
            super.start();
        }
    }
    @Override
    public void run()
    {
        //字節(jié)輸入流
        InputStream inputStream = null;
        //字節(jié)輸出流
        OutputStream outputStream = null;
        try
        {
            inputStream = m_socket.getInputStream();
            outputStream = m_socket.getOutputStream();
            String info = "";
            //按byte讀
            byte[] bytes = new byte[1];
            while (m_isRuning)
            {
                //檢測(cè)心跳
                if (System.currentTimeMillis() - m_lastReceiveTime > TIMEOUT)
                {
                    m_isRuning = false;
                    //跳出,執(zhí)行finally塊
                    break;
                }
                //返回下次調(diào)用可以不受阻塞地從此流讀取或跳過(guò)的估計(jì)字節(jié)數(shù),如果等于0則表示已經(jīng)讀完
                if (inputStream.available() > 0)
                {
                    //重置接收到數(shù)據(jù)的最新時(shí)間
                    m_lastReceiveTime = System.currentTimeMillis();
                    inputStream.read(bytes);
                    String tempStr = ByteArrayToHexStr(bytes) ;
                    info += tempStr;
                    //已經(jīng)讀完
                    if (inputStream.available() == 0)
                    {
                        System.out.println(">>>線程" + this.getId() + "收到:" + info);
                        String responseStr = "Hello";
                        //響應(yīng)內(nèi)容
                        String hexStr = StrToHexStr(responseStr);
                        hexStr = hexStr.replaceAll("0[x|X]|,","");
                        byte[] byteArray = HexStrToByteArray(hexStr);
                        outputStream.write(byteArray);
                        outputStream.flush();
                        //重置,不然每次收到的數(shù)據(jù)都會(huì)累加起來(lái)
                        info = "";
                        System.out.println(">>>線程" + this.getId() + "回應(yīng):" + responseStr);
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        //關(guān)閉資源
        finally
        {
            System.out.println(">>>線程" + this.getId() + "的連接已斷開(kāi)\n");
            try
            {
                if (outputStream != null)
                    outputStream.close();
                if (inputStream != null)
                    inputStream.close();
                if (m_socket != null)
                    m_socket.close();
                m_isRuning = false;
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    /**
     * byte[]轉(zhuǎn)16進(jìn)制Str
     *
     * @param byteArray
     */
    public static String ByteArrayToHexStr(byte[] byteArray)
    {
        if (byteArray == null)
        {
            return null;
        }
        char[] hexArray = HEXSTRING.toCharArray();
        char[] hexChars = new char[byteArray.length * 2];
        for (int i = 0; i < byteArray.length; i++)
        {
            int temp = byteArray[i] & 0xFF;
            hexChars[i * 2] = hexArray[temp >>> 4];
            hexChars[i * 2 + 1] = hexArray[temp & 0x0F];
        }
        return new String(hexChars);
    }
    /**
     * Str轉(zhuǎn)16進(jìn)制Str
     *
     * @param str
     * @return
     */
    public static String StrToHexStr(String str)
    {
        //根據(jù)默認(rèn)編碼獲取字節(jié)數(shù)組
        byte[] bytes = str.getBytes();
        StringBuilder stringBuilder = new StringBuilder(bytes.length * 2);
        //將字節(jié)數(shù)組中每個(gè)字節(jié)拆解成2位16進(jìn)制整數(shù)
        for (int i = 0; i < bytes.length; i++)
        {
            stringBuilder.append("0x");
            stringBuilder.append(HEXSTRING.charAt((bytes[i] & 0xf0) >> 4));
            stringBuilder.append(HEXSTRING.charAt((bytes[i] & 0x0f) >> 0));
            //去掉末尾的逗號(hào)
            if (i != bytes.length - 1)
            {
                stringBuilder.append(",");
            }
        }
        return stringBuilder.toString();
    }
    /**
     * 16進(jìn)制Str轉(zhuǎn)byte[]
     *
     * @param hexStr 不帶空格、不帶0x、不帶逗號(hào)的16進(jìn)制Str,如:06EEF7F1
     * @return
     */
    public static byte[] HexStrToByteArray(String hexStr)
    {
        byte[] byteArray = new byte[hexStr.length() / 2];
        for (int i = 0; i < byteArray.length; i++)
        {
            String subStr = hexStr.substring(2 * i, 2 * i + 2);
            byteArray[i] = ((byte) Integer.parseInt(subStr, 16));
        }
        return byteArray;
    }
}

開(kāi)啟服務(wù)端

 
import java.net.ServerSocket;
import java.net.Socket;
public class MySocketServer
{
    public static void main(String[] args)
    {
        try
        {
            System.out.println(">>>服務(wù)啟動(dòng),等待終端的連接\n");
            ServerSocket server = new ServerSocket(8888);
            int count = 0;
            while (true)
            {
                //開(kāi)啟監(jiān)聽(tīng)
                Socket socket = server.accept();
                count++;
                System.out.println(">>>開(kāi)啟第" + count + "次長(zhǎng)連接...");
                ServerThread thread = new ServerThread(socket);
                thread.start();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中POST、GET、@RequestBody和@RequestParam區(qū)別詳析

    Java中POST、GET、@RequestBody和@RequestParam區(qū)別詳析

    在前后端傳json數(shù)據(jù)進(jìn)行交互的時(shí)候,同學(xué)們會(huì)經(jīng)常用到的兩個(gè)注解,@RequestBody和@RequestParam主要是用來(lái)接收前端傳給后端的json數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Java中POST、GET、@RequestBody和@RequestParam區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • Java面試題沖刺第十天--MyBatis2

    Java面試題沖刺第十天--MyBatis2

    這篇文章主要為大家分享了最有價(jià)值的三道MyBatis框架面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java基礎(chǔ)第五篇 實(shí)施接口

    Java基礎(chǔ)第五篇 實(shí)施接口

    在public和private的封裝機(jī)制,我們實(shí)際上同時(shí)定義了類和接口,類和接口混合在一起。Java還提供了interface這一語(yǔ)法。這一語(yǔ)法將接口從類的具體定義中剝離出來(lái),構(gòu)成一個(gè)獨(dú)立的主體,下面文章內(nèi)容將為大家做詳細(xì)介紹
    2021-09-09
  • Java字符串處理全解析(String、StringBuilder與StringBuffer)

    Java字符串處理全解析(String、StringBuilder與StringBuffer)

    這篇文章主要介紹了Java字符串處理全解析(String、StringBuilder與StringBuffer),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-04-04
  • java使用poi讀取doc和docx文件的實(shí)現(xiàn)示例

    java使用poi讀取doc和docx文件的實(shí)現(xiàn)示例

    這篇文章主要介紹了java使用poi讀取doc和docx文件的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • SpringBoot和Springfox(Swagger)版本不兼容的解決方案

    SpringBoot和Springfox(Swagger)版本不兼容的解決方案

    documentationPluginsBootstrapper這個(gè) bean 無(wú)法正常啟動(dòng),原因是遇到了空指針異常(NullPointerException),這通常是由于 Spring Boot 和 Springfox 的版本不兼容導(dǎo)致的路徑匹配策略沖突,本文給大家介紹了SpringBoot和Springfox(Swagger)版本不兼容的解決方案
    2024-12-12
  • 關(guān)于scanner.nextInt()等next()和scanner.nextIine()連用注意事項(xiàng)

    關(guān)于scanner.nextInt()等next()和scanner.nextIine()連用注意事項(xiàng)

    這篇文章主要介紹了關(guān)于scanner.nextInt()等next()和scanner.nextIine()連用注意事項(xiàng),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2023-04-04
  • Java設(shè)計(jì)模式之迭代器模式解析

    Java設(shè)計(jì)模式之迭代器模式解析

    這篇文章主要介紹了Java設(shè)計(jì)模式之迭代器模式解析,迭代器模式提供一個(gè)對(duì)象來(lái)順序訪問(wèn)聚合對(duì)象中的一系列數(shù)據(jù),而不暴露聚合對(duì)象的內(nèi)部表示,本文提供了部分代碼,需要的朋友可以參考下
    2023-09-09
  • 詳解Java HashMap實(shí)現(xiàn)原理

    詳解Java HashMap實(shí)現(xiàn)原理

    HashMap是基于哈希表的Map接口實(shí)現(xiàn),提供了所有可選的映射操作,并允許使用null值和null建,不同步且不保證映射順序。本文將記錄一下研究HashMap實(shí)現(xiàn)原理。
    2017-01-01
  • Java?Spring?Dubbo三種SPI機(jī)制的區(qū)別

    Java?Spring?Dubbo三種SPI機(jī)制的區(qū)別

    這篇文章主要介紹了Java?Spring?Dubbo三種SPI機(jī)制的區(qū)別,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-08-08

最新評(píng)論