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

使用Java完成Socket文件傳輸方式

 更新時間:2023年09月28日 16:29:13   作者:牛言牛語  
這篇文章主要介紹了使用Java完成Socket文件傳輸方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Java完成Socket文件傳輸

TCP協(xié)議的Socket文件傳輸

分別使用三個類(TCPFileUpload_Server服務器端、TCPFileUpload_Client客戶端、StreamUtils工具類)完成圖片的傳輸。

同樣先運行服務器端文件,再運行客戶端文件

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * 服務器端
 */
public class TCPFileUpload_Server {
    public static void main(String[] args) throws Exception {
        //思路
        //在本機 的8888端口監(jiān)聽, 等待連接
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服務器端,監(jiān)聽8888端口,等待連接");
        //當沒有客戶端連接8888端口時,程序會 阻塞, 等待連接
        //如果有客戶端連接,則會返回Socket對象,程序繼續(xù)
        Socket socket = serverSocket.accept();
        //通過socket.getInputStream() 讀取客戶端寫入到數(shù)據(jù)通道的數(shù)據(jù), 并轉(zhuǎn)換成字節(jié)數(shù)組
        BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
        //寫入指定路徑
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("src\\G.jpg"));
        bufferedOutputStream.write(bytes);
        //關閉IO流
        bufferedOutputStream.close();
        //向客戶端回復收到圖片
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bufferedWriter.write("收到圖片!");
        bufferedWriter.flush();
        socket.shutdownOutput();
        //關閉所有流
        bufferedWriter.close();
        bufferedInputStream.close();
        socket.close();
        serverSocket.close();
    }
}
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
 * 客戶端
 */
public class TCPFileUpload_Client {
    public static void main(String[] args) throws Exception {
        //連接服務端 (ip , 端口)
        //解讀:連接本機的 8888端口, 如果連接成功,返回Socket對象
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
        System.out.println("客戶端 連接端口:" + socket.getPort());
        //創(chuàng)建讀取磁盤文件IO流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("src/P.jpg"));
        //獲取字節(jié)數(shù)組
        byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
        //通過Socket獲取到輸出流,將bytes發(fā)送到服務端
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
        bufferedOutputStream.write(bytes);
        //關閉流對象,socket,刷新,添加終止符
        bufferedInputStream.close();
        bufferedOutputStream.flush();
        socket.shutdownOutput();
        //接受回復消息
        //此處可調(diào)用Utils的方法
//        String s = "";
//        while ((s = bufferedReader.readLine()) != null)
//            System.out.println(s);
        System.out.println(StreamUtils.streamToString(socket.getInputStream()));
        //關閉所有流
        bufferedOutputStream.close(); //socket的包裝流不要過早關閉
        socket.close();
    }
}
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
 * 此類用于演示關于流的讀寫方法
 */
public class StreamUtils {
    /**
     * 功能:將輸入流轉(zhuǎn)換成byte[]
     *
     * @param is 輸入流
     * @return byte數(shù)組
     * @throws Exception IO流異常
     */
    public static byte[] streamToByteArray(InputStream is) throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();//創(chuàng)建輸出流對象
        byte[] b = new byte[1024];
        int len;
        while ((len = is.read(b)) != -1) {
            bos.write(b, 0, len);
        }
        byte[] array = bos.toByteArray();
        bos.close();
        return array;
    }
    /**
     * 功能:將InputStream轉(zhuǎn)換成String
     *
     * @param is 輸入流
     * @return 字符串
     * @throws Exception IO流異常
     */
    public static String streamToString(InputStream is) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder builder = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) { //當讀取到 null時,就表示結(jié)束
            builder.append(line + "\r\n");
        }
        return builder.toString();
    }
}

Java Socket數(shù)據(jù)傳輸基礎以及優(yōu)化

學到Java的TCP的Socket傳輸數(shù)據(jù)有些錯誤和心得在此記下

UDP和TCP

UDP:無連接通信協(xié)議,數(shù)據(jù)的發(fā)送端和接收端不用構建邏輯連接(發(fā)送時發(fā)送端無需確認接收端的存在,接收端無需返回相映給發(fā)送端)

  • UDP協(xié)議資源消耗小,通信效率高,通常用于音頻、視頻接收和普通數(shù)據(jù)的傳輸
  • 但是又因為UDP面向無連接性,不能保證數(shù)據(jù)的完整性,因此在傳輸重要數(shù)據(jù)的時候不推薦使用UDP協(xié)議

TCP:在發(fā)送數(shù)據(jù)的準備階段,客戶端與服務器之間的三次交互,以保證連接的可靠性

  • 第一次握手:客戶端向服務器發(fā)出連接請求
  • 第二次握手:服務器通知客戶端收到了連接請求
  • 第三次握手:客戶端再次向服務器發(fā)送確認信息,確認連接
  • TCP的傳輸安全性高于UDP,下載文件和瀏覽網(wǎng)頁等使用的都是TCP

TCP的socket通信

  • 一種情況:客戶端發(fā)送信息和接收信息需要輸入輸出流兩個流,同理服務器也是這樣,為了避免生成許許多多的流對象,所以可以利用socket中自帶的輸入輸出流進行數(shù)據(jù)交互

Socket使用方法

1.客戶端構造函數(shù)

 Socket socket = new Socket(ip,port); 

注解: 因為TCP是邏輯連接式的傳輸,所以客戶端需要得知服務器的ip和端口

使用getOutputStream() 方法獲得輸出流

OutputStream cos = socket.getOutputStream();
cos.write("你好服務器".getBytes());  

注解:write使用字節(jié)輸入輸出,需要經(jīng)過 字符–字節(jié)–字符的轉(zhuǎn)換,轉(zhuǎn)換的方法 getBytes() , new String(buf,0,len) ,如果想要直接輸出可以使用打印流 printStream

使用getInputStream方法獲得輸入流

InputStream cis = socket.getInputStream()
//設置一個緩沖數(shù)組 temp數(shù)組大小大于所接收的數(shù)據(jù)量
byte[] temp = new byte[1024];
int len = cis.read(temp);
//將所接守的字節(jié)轉(zhuǎn)換為字符串 這里使用 temp.toString()會有亂碼
System.out.println(new String(temp,0,len));

注意最后要釋放資源

socket.close();

2.服務器

服務器首先要創(chuàng)建ServerSocket設置端口號

ServerSocket server = new ServerSocket(port:8888);

注解:注意當編寫循環(huán)響應時server的定義需要在while(true)循環(huán)之外,不然會顯示端口被占用的情況

Exception in thread "main" java.net.BindException: Address already in use: NET_Bind

然后使用accept()方法返回Socket對象

Socket socket = server.accept();

accept() 方法具有阻塞作用,后面的實例會提到

通過accept()獲得socket對象后,后面的操作方式與客戶端的socket其實是一致的了

//獲得流對象
InputStream sis = socket.getInputStream();
OutputStream sos = socket.getOutputStream();
//打印從客戶端獲得的數(shù)據(jù)
byte[] temp = new btye[1024];
sis.read(temp);
System.out.println(new String(temp));
//對客戶端發(fā)出返回信息
sos.write("你也好,客戶端".getBytes());

注意最后要釋放資源

socket.close();
server.close();

總的應用代碼,圖片傳輸

客戶端

import java.io.*;
import java.net.*;
public class TCPClient {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\子陌\\Pictures\\1.jpg");
        Socket socket = new Socket("192.168.1.8",8888);
        OutputStream cos = socket.getOutputStream();
        InputStream cis = socket.getInputStream();
        int len =0;
        byte[] bytes = new byte[1024];
        while((len = fis.read(bytes))!=-1){
            cos.write(bytes,0,len);
        }
        socket.shutdownOutput();
        byte[] bytes1 = new byte[1024];
        int len1=0;
        len1 =cis.read(bytes1);
        System.out.println(new String(bytes1));
        socket.close();
        fis.close();
    }
}

服務器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class TCPSever {
    public static void main(String[] args) throws IOException {
        //這里ServerSocket要放到外面
        ServerSocket server = new ServerSocket(8888);
        while(true) { 
            new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            //先把accept響應放到前面
                            Socket socket = server.accept();
                            String fileName = "itcast" + System.currentTimeMillis() + new Random().nextInt();
                            File file = new File("D:\\TCPUpLoad");
                            if (!file.exists()) {
                                file.mkdirs();
                            }
                            FileOutputStream fos = new FileOutputStream(file + "\\" + fileName + ".jpg");//這里file既是File類也可以當作路徑名稱
                            //FileOutPutStream 會自動生成空文件
                            InputStream sis = socket.getInputStream();
                            OutputStream sos = socket.getOutputStream();
                            int len = 0;
                            byte[] bytes = new byte[1024];
                            while ((len = sis.read(bytes)) != -1) {
                                fos.write(bytes, 0, len);
                            }
                            sos.write("已經(jīng)收到".getBytes());
                            socket.close();
                            fos.close();
                            //重點:要將資源全部釋放,不然會占用線程或者端口
                        }catch(IOException e)
                        {
                            System.out.println(e);
                        }
                    }
                }).start();
        }
        //server.close();
    }
}

代碼中需要注意的點

1.服務器ServerSocket需要放到while外部,while的目的是能夠隨時響應客戶端的請求

2.fileName 使用了

String fileName = "itcast" + System.currentTimeMillis() + new Random().nextInt(9999); 

這也就是為什么從網(wǎng)上下載的圖片有一大堆數(shù)字名字的原因

3.利用了多線程重寫Runnable中的 run 方法,運用了匿名內(nèi)部類,大大提高了服務器的響應速度

4.這里涉及之前提到的一個容易出bug的問題,server.accept() 的阻塞作用,因為會服務器會不斷的while循環(huán)就會開啟很多線程,如果

FileOutStream fos = new FileOutStream(...) 

運行先于server.accept(),就會每產(chǎn)生一個線程就創(chuàng)建一個空文件 我就是犯了這個錯誤導致電腦多了幾萬個帶.jpg的空文件

5.服務器和客戶端要同時運作時需要知道自己的ip地址,可以在運行的 cmd 中 輸入 ipconfig 進行查詢

6.Runnable 中的 run 方法并不能自動拋出異常,只能手動 try catch 詳見上方代碼

7.還有一個阻塞問題就是,當客戶端讀取結(jié)束后傳輸給服務器,但是服務器并不知道讀取結(jié)束就會導致客戶端和服務器的同時阻塞,這時需要 Socket 中的 shutdownOutput() 方法告訴服務器已經(jīng)讀取完畢

 while((len = fis.read(bytes))!=-1)
       {
            cos.write(bytes,0,len);
        }
        socket.shutdownOutput();

總結(jié)

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

相關文章

  • java實現(xiàn)ATM機系統(tǒng)(2.0版)

    java實現(xiàn)ATM機系統(tǒng)(2.0版)

    這篇文章主要為大家詳細介紹了java實現(xiàn)ATM機系統(tǒng)2.0版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 使用Springboot打成jar包thymeleaf的問題

    使用Springboot打成jar包thymeleaf的問題

    這篇文章主要介紹了使用Springboot打成jar包thymeleaf的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Spring Security基于HttpRequest配置權限示例詳解

    Spring Security基于HttpRequest配置權限示例詳解

    這篇文章主要介紹了Spring Security基于HttpRequest配置權限示例詳解,我們在配置中配置的url被封裝成RequestMatcher,而hasRole被封裝成AuthorityAuthorizationManager,本文結(jié)合示例代碼講解的非常詳細,需要的朋友可以參考下
    2024-03-03
  • Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    這篇文章主要介紹了Java中Double保留后小數(shù)位的幾種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-07-07
  • Java文件操作之IO流 File類的使用詳解

    Java文件操作之IO流 File類的使用詳解

    在java中提供有對于文件操作系統(tǒng)的支持,這個支持在java.io.File類中進行了定義,也就是說在整個java.io包中File類是唯一一個與文件本身操作有關的類(創(chuàng)建,刪除,重命名)有關的類,而如果想要進行File類的操作,我們需要提供有完整的路徑支持,而后可以調(diào)用相應的方法進行處理
    2021-09-09
  • gRPC中interceptor攔截器的使用教程

    gRPC中interceptor攔截器的使用教程

    gRPC中的interceptor攔截器分為客戶端攔截器和服務端攔截器,分別是在客戶端和服務端的請求被發(fā)送出去之前進行處理的邏輯,下面就跟隨小編一起學習一下interceptor攔截器的具體使用吧
    2023-08-08
  • springboot配置http跳轉(zhuǎn)https的過程

    springboot配置http跳轉(zhuǎn)https的過程

    SSL是為網(wǎng)絡通信提供安全以及保證數(shù)據(jù)完整性的的一種安全協(xié)議,SSL在網(wǎng)絡傳輸層對網(wǎng)絡連接進行加密,這篇文章主要介紹了springboot配置http跳轉(zhuǎn)https的過程,需要的朋友可以參考下
    2023-04-04
  • 幾道java循環(huán)練習題(適合新人)

    幾道java循環(huán)練習題(適合新人)

    這篇文章主要給大家介紹了幾道java循環(huán)練習題,非常適合剛?cè)腴T的java新人,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Java生成隨機數(shù)的2種示例方法代碼

    Java生成隨機數(shù)的2種示例方法代碼

    在Java中,生成隨機數(shù)有兩種方法。1是使用Random類。2是使用Math類中的random方法??聪旅娴睦邮褂冒?/div> 2013-11-11
  • 詳解OpenCV For Java環(huán)境搭建與功能演示

    詳解OpenCV For Java環(huán)境搭建與功能演示

    這篇文章主要介紹了x詳解OpenCV For Java環(huán)境搭建與功能演示,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04

最新評論