亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java?Socket實現(xiàn)文件發(fā)送和接收功能以及遇到的Bug問題

 更新時間:2024年08月12日 08:57:22   作者:I?am?Groot!  
這篇文章主要介紹了Java?Socket實現(xiàn)文件發(fā)送和接收功能以及遇到的Bug問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Java Socket實現(xiàn)文件發(fā)送和接收功能

在Java中,如何用Socket實現(xiàn)文件的發(fā)送和接收功能?

我的第一版代碼

文件發(fā)送:

public void sendFile(String filePath) {//過長、過多的密文信息直接發(fā)送文件
		File file = new File(filePath);
        try {
        	DataOutputStream d_out = new DataOutputStream(socket.getOutputStream());
            FileInputStream f_in = new FileInputStream(file);
            int all = 0;
            byte[] buffer = new byte[4096];
            int read = 0;
            while ((read = (f_in.read(buffer))) > 0) {
                d_out.write(buffer, 0, read);
                all += read;
            }
            System.out.println("Send file length: "+all);
            d_out.flush();
            f_in.close();
            d_out.close();//注意這一行
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

文件接收:

public void receiveFile(String filePath) {//接收文件
		try {
			DataOutputStream dosOutputStream = new DataOutputStream(new FileOutputStream(filePath));
			byte[] buf = new byte[4096];
			int len = 0;
			System.out.println("開始接收文件!");
			d_in = new DataInputStream(sock.getInputStream());
			while((len = d_in.read(buf)) != -1) { 
				dosOutputStream.write(buf, 0, len);
			}
			dosOutputStream.flush();
			System.out.println("文件接收結束!");
			//d_in.close();
			dosOutputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

上面的寫法的確實現(xiàn)了文件發(fā)送和接收的功能(Socket初始化這里沒有給出,大家可以自行補充這部分,是可以運行的),但是這個實現(xiàn)方式存在一個很致命的問題,就是只能完成一次文件的發(fā)送和接收。

在此之后如果你想再調(diào)用文件的發(fā)送和接收方法,就會遇到如下"Socket is closed"這個問題:

為什么會遇到這一問題

首先肯定是因為Socket被我關閉了,但我并沒有寫"socket.close();"這樣的代碼呀,為什么還是被關閉了呢?

我們把注意力放到上面提到的文件發(fā)送的代碼上,注意這一行:

d_out.close();

這里原本的目的是把DataOutputStream給關閉掉,結束我們的文件發(fā)送輸出流。

但是當我們關閉DataOutputStream時,Socket也會隨之關閉,這便有了后面想再次執(zhí)行sendFile方法時,出現(xiàn)的"Socket is closed"問題。

所以為了能連續(xù)多次地發(fā)送、接收不同的文件,這一行代碼肯定是不能要了。

把這行代碼注釋掉,修改后的代碼為

文件發(fā)送:

public void sendFile(String filePath) {//過長、過多的密文信息直接發(fā)送文件
		File file = new File(filePath);
        try {
        	DataOutputStream d_out = new DataOutputStream(socket.getOutputStream());
            FileInputStream f_in = new FileInputStream(file);
            int all = 0;
            byte[] buffer = new byte[4096];
            int read = 0;
            while ((read = (f_in.read(buffer))) > 0) {
                d_out.write(buffer, 0, read);
                all += read;
            }
            System.out.println("Send file length: "+all);
            d_out.flush();
            f_in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

文件接收:

public void receiveFile(String filePath) {//接收文件
		try {
			DataOutputStream dosOutputStream = new DataOutputStream(new FileOutputStream(filePath));
			byte[] buf = new byte[4096];
			int len = 0;
			System.out.println("開始接收文件!");
			d_in = new DataInputStream(sock.getInputStream());
			while((len = d_in.read(buf)) != -1) { 
				dosOutputStream.write(buf, 0, len);
			}
			dosOutputStream.flush();
			System.out.println("文件接收結束!");
			//d_in.close();
			dosOutputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

這樣修改后又遇到了新的問題

那就是在接收文件時,發(fā)生了阻塞的現(xiàn)象:

控制臺就一直卡在“開始接收文件!”這行輸出這里,顯然是因為文件接收的while循環(huán)被卡住了,但剛剛明明沒有這個問題啊,為什么注釋掉“sendFile”中的d_out.close();會使得“receiveFile”的while循環(huán)被卡住呢?

while((len = d_in.read(buf)) != -1) { 
    dosOutputStream.write(buf, 0, len);
}

這篇文章給出了比較好的解答:http://chabaoo.cn/program/325734b3l.htm

原因如下

“只要客戶端的DataOutputStream不close掉,那么服務端的DataInputStream read就永遠不等于-1。即使文件的數(shù)據(jù)已經(jīng)傳完了,DataInputStream依舊會等著客戶端DataOutputStream再傳數(shù)據(jù)過來。最后只能通過判斷文件的的大小來確認文件是否已經(jīng)傳輸完成。”

這便是為什么在d_out.close();沒有被注釋前是沒有這個Bug的:因為當我們將DataOutputStream close掉時,接收方的while循環(huán)也就結束了。

所以我們現(xiàn)在可以采用len的實際長度來判斷是否已經(jīng)傳輸完成,修改后的代碼如下:

while((len = d_in.read(buf)) != -1) { 
    dosOutputStream.write(buf, 0, len);
	if(len < buf.length) break;
}

即:判斷buf是否被填滿,沒有填滿(len<buf.length)則代表已經(jīng)接收完畢

經(jīng)過測試,問題解決

最終代碼如下:

文件發(fā)送:

?
public void sendFile(String filePath) {//發(fā)送文件
		File file = new File(filePath);
        try {
        	DataOutputStream d_out = new DataOutputStream(socket.getOutputStream());
            FileInputStream f_in = new FileInputStream(file);
            int all = 0;
            byte[] buffer = new byte[4096];
            int read = 0;
            while ((read = (f_in.read(buffer))) > 0) {
                d_out.write(buffer, 0, read);
                all += read;
            }
            System.out.println("Send file length: "+all);
            d_out.flush();
            f_in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

?

文件接收:

public void receiveFile(String filePath) {//接收文件
		try {
			DataOutputStream dosOutputStream = new DataOutputStream(new FileOutputStream(filePath));
			byte[] buf = new byte[4096];
			int len = 0;
			System.out.println("開始接收文件!");
			d_in = new DataInputStream(sock.getInputStream());
			while((len = d_in.read(buf)) != -1) { 
				dosOutputStream.write(buf, 0, len);
                if(len < buf.length) break;
			}
			dosOutputStream.flush();
			System.out.println("文件接收結束!");
			dosOutputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

總結

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

相關文章

  • java實現(xiàn)漢字轉unicode與漢字轉16進制實例

    java實現(xiàn)漢字轉unicode與漢字轉16進制實例

    這篇文章主要介紹了java實現(xiàn)漢字轉unicode與漢字轉16進制的實現(xiàn)方法,是Java操作漢字編碼轉換的一個典型應用,非常具有實用價值,需要的朋友可以參考下
    2014-10-10
  • springboot 增加過濾器方法操作示例

    springboot 增加過濾器方法操作示例

    這篇文章主要介紹了springboot 增加過濾器方法操作,結合實例形式分析了springboot過濾器配置、加載等相關操作技巧,需要的朋友可以參考下
    2019-12-12
  • hashMap擴容時應該注意這些死循環(huán)問題

    hashMap擴容時應該注意這些死循環(huán)問題

    今天給大家?guī)淼氖顷P于Java的相關知識,文章圍繞著hashMap擴容時的死循環(huán)問題展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Spring中的之啟動過程obtainFreshBeanFactory詳解

    Spring中的之啟動過程obtainFreshBeanFactory詳解

    這篇文章主要介紹了Spring中的之啟動過程obtainFreshBeanFactory詳解,在refresh時,prepareRefresh后,馬上就調(diào)用了obtainFreshBeanFactory創(chuàng)建beanFactory以及掃描bean信息(beanDefinition),并通過BeanDefinitionRegistry注冊到容器中,需要的朋友可以參考下
    2024-02-02
  • 擴展tk.mybatis的流式查詢功能實現(xiàn)

    擴展tk.mybatis的流式查詢功能實現(xiàn)

    mybatis查詢默認是一次獲取全部,如果數(shù)據(jù)過于龐大,就會導致OOM問題,本文就介紹了tk.mybatis 流式查詢,具有一定的參考價值,感興趣的可以了解一下
    2021-12-12
  • Java虛擬機JVM棧溢出的問題解決

    Java虛擬機JVM棧溢出的問題解決

    Java虛擬機棧溢出是指在Java程序中,當線程調(diào)用的方法層級過深,導致棧空間溢出的情況,本文就詳細的介紹了下產(chǎn)生的原因以及優(yōu)化,具有一定的參考價值,感興趣的可以了解一下
    2023-08-08
  • Java使用easypoi快速導入導出的實現(xiàn)

    Java使用easypoi快速導入導出的實現(xiàn)

    這篇文章主要介紹了實現(xiàn)Java使用easypoi快速導入導出的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Java HttpServletResponse響應實現(xiàn)過程詳解

    Java HttpServletResponse響應實現(xiàn)過程詳解

    這篇文章主要介紹了Java HttpServletResponse響應實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • SpringBoot JVM參數(shù)調(diào)優(yōu)方式

    SpringBoot JVM參數(shù)調(diào)優(yōu)方式

    這篇文章主要介紹了SpringBoot JVM參數(shù)調(diào)優(yōu)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java自定義注解驗證手機格式的實現(xiàn)示例

    java自定義注解驗證手機格式的實現(xiàn)示例

    這篇文章主要介紹了java自定義注解驗證手機格式的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03

最新評論