最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

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

  • 發(fā)送時:將String轉(zhuǎn)byte[]
  • 接收時:將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);
            //得到一個輸出流,用于向服務(wù)器發(fā)送數(shù)據(jù)
            OutputStream outputStream = socket.getOutputStream();
            System.out.println("請輸入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();
                //得到一個輸入流,用于接收服務(wù)器響應(yīng)的數(shù)據(jù)
                InputStream inputStream = socket.getInputStream();
                byte[] bytes = new byte[1]; // 一次讀取一個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("收到來自服務(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對象的available()方法判斷客戶端的內(nèi)容是否發(fā)送完畢

dataInputStream.available()

官方解釋:

返回此輸入流下一個方法調(diào)用可以不受阻塞地從此輸入流讀取(或跳過)的估計字節(jié)數(shù)。

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

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

用我的大白話就是:返回剩余未讀長度

 
import java.io.*;
import java.net.Socket;
/**
 * 長連接
 */
public class ServerThread extends Thread
{
    //16進(jìn)制數(shù)字字符集
    public static final String HEXSTRING = "0123456789ABCDEF";
    //心跳超時時間
    private static final int TIMEOUT = 60 * 1000;
    private Socket m_socket;
    //接收到數(shù)據(jù)的最新時間
    private long m_lastReceiveTime = System.currentTimeMillis();
    //該線程是否正在運行
    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() + "啟動失敗,該線程正在執(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)
            {
                //檢測心跳
                if (System.currentTimeMillis() - m_lastReceiveTime > TIMEOUT)
                {
                    m_isRuning = false;
                    //跳出,執(zhí)行finally塊
                    break;
                }
                //返回下次調(diào)用可以不受阻塞地從此流讀取或跳過的估計字節(jié)數(shù),如果等于0則表示已經(jīng)讀完
                if (inputStream.available() > 0)
                {
                    //重置接收到數(shù)據(jù)的最新時間
                    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ù)都會累加起來
                        info = "";
                        System.out.println(">>>線程" + this.getId() + "回應(yīng):" + responseStr);
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        //關(guān)閉資源
        finally
        {
            System.out.println(">>>線程" + this.getId() + "的連接已斷開\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ù)組中每個字節(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));
            //去掉末尾的逗號
            if (i != bytes.length - 1)
            {
                stringBuilder.append(",");
            }
        }
        return stringBuilder.toString();
    }
    /**
     * 16進(jìn)制Str轉(zhuǎn)byte[]
     *
     * @param hexStr 不帶空格、不帶0x、不帶逗號的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;
    }
}

開啟服務(wù)端

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

總結(jié)

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

相關(guān)文章

  • 解決創(chuàng)建springboot后啟動報錯:Failed?to?bind?properties?under‘spring.datasource‘

    解決創(chuàng)建springboot后啟動報錯:Failed?to?bind?properties?under‘spri

    在Spring?Boot項目中,application.properties和application.yml是用于配置參數(shù)的兩種文件格式,properties格式簡潔但不支持層次結(jié)構(gòu),而yml格式支持層次性,可讀性更好,在yml文件中,要注意細(xì)節(jié),比如冒號后面需要空格
    2024-10-10
  • Maven配置中repositories、distributionManagement、pluginRepositories用法及將已有jar包部署到私服

    Maven配置中repositories、distributionManagement、pluginRepositori

    這篇文章主要介紹了Maven配置中repositories、distributionManagement、pluginRepositories用法及將已有jar包部署到私服,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java9的一些新特性介紹

    Java9的一些新特性介紹

    這篇文章主要介紹了Java9的一些新特性介紹,Java隨著其開源的特點和甲骨文的推動正在不斷改進(jìn)中,需要的朋友可以參考下
    2015-07-07
  • 如何通過javacv實現(xiàn)圖片去水?。ǜ酱a)

    如何通過javacv實現(xiàn)圖片去水?。ǜ酱a)

    這篇文章主要介紹了如何通過javacv實現(xiàn)圖片去水印(附代碼),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • SpringBoot實現(xiàn)調(diào)用自定義的應(yīng)用程序((最新推薦)

    SpringBoot實現(xiàn)調(diào)用自定義的應(yīng)用程序((最新推薦)

    這篇文章主要介紹了SpringBoot實現(xiàn)調(diào)用自定義的應(yīng)用程序的相關(guān)知識,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Netty分布式固定長度解碼器實現(xiàn)原理剖析

    Netty分布式固定長度解碼器實現(xiàn)原理剖析

    這篇文章主要為大家介紹了Netty分布式固定長度解碼器原理剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • VSCode中搭建JAVA+MAVEN開發(fā)環(huán)境的完整步驟

    VSCode中搭建JAVA+MAVEN開發(fā)環(huán)境的完整步驟

    Maven是一個Java項目管理和構(gòu)建工具,它可以定義項目結(jié)構(gòu)、項目依賴,并使用統(tǒng)一的方式進(jìn)行自動化構(gòu)建,是Java項目不可缺少的工具,這篇文章主要介紹了VSCode中搭建JAVA+MAVEN開發(fā)環(huán)境的完整步驟,需要的朋友可以參考下
    2026-02-02
  • java實現(xiàn)微信掃碼支付功能

    java實現(xiàn)微信掃碼支付功能

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)微信掃碼支付功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Java8 Lambda和Invokedynamic詳情

    Java8 Lambda和Invokedynamic詳情

    關(guān)于Java8的Lambda 我們可以將lambda表達(dá)式與新的Streams API結(jié)合起來,以表達(dá)豐富的數(shù)據(jù)處理查詢,下面文章小編就列舉簡單的例子給大家介說吧,感興趣的小伙伴可以參考下面文章的具體內(nèi)容奧
    2021-09-09
  • 基于Java創(chuàng)建一個訂單類代碼實例

    基于Java創(chuàng)建一個訂單類代碼實例

    這篇文章主要介紹了基于Java創(chuàng)建一個訂單類代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12

最新評論

前郭尔| 平塘县| 马关县| 竹山县| 泰州市| 佳木斯市| 高邮市| 南平市| 长寿区| 荆州市| 浙江省| 吐鲁番市| 隆林| 桂林市| 淄博市| 綦江县| 锦屏县| 江油市| 许昌市| 博客| 湘乡市| 绥棱县| 普定县| 汽车| 垦利县| 西昌市| 贺兰县| 贵溪市| 勐海县| 沈阳市| 禹州市| 遂宁市| 宜昌市| 洱源县| 旬邑县| 田林县| 洛隆县| 招远市| 宁远县| 乾安县| 祁阳县|