Java 網路編程之TCP通訊和簡單的檔案上傳功能

來源:互聯網
上載者:User

Java 網路編程之TCP通訊和簡單的檔案上傳功能

TCP通訊需要明確的幾點:

  1. tcp通訊是連線導向的,需要先啟動服務端,再啟動用戶端。
  2. 用戶端和服務端都要建立通訊端對象,用戶端需要指定服務端通訊端(ip+port),而服務端必須指定服務連接埠。
    Socket client_socket = new Socket("192.168.100.17",8888); //用戶端通訊端(Socket類的通訊端為已串連通訊端)ServerSocket listen_socket = new ServerSocket(8888);      //服務端通訊端,此時為監聽通訊端(已經bind()地址和連接埠了)
  3. 服務端需要使用accept()方法將監聽通訊端轉變為已串連通訊端。這個監聽通訊端可以產生多個已串連通訊端,這樣串連後還能監聽其他用戶端的請求。因此,這裡應該使用多線程實現並發訪問。獲得了已串連通訊端,就可以擷取很多用戶端的資訊,例如用戶端的ip地址,發送請求的連接埠等。

    Socket server_scoket = socket.accept();Socket server_scoket2 = socket.accept();Socket server_scoket3 = socket.accept();

    服務端要實現並發串連,大致使用如下代碼:其中ThreadTask是線程任務對象。

    public static void main(String[] args) throws IOException { ServerSocket listen_sock = new ServerSocket(8888);   //監聽通訊端只需建立一個,因此在任務之外 while (true) {   //每建立一個串連,就開啟一個線程     Socket conn_sock = listen_sock.accept();  //沒有新串連進來時,main主線程阻塞在此     new Thread(new ThreadTask(conn_sock)).start(); }}
  4. 用戶端需要根據已串連通訊端擷取輸出資料流,服務端需要根據通訊端擷取輸入資料流。當然,既然有了已串連通訊端,那麼擷取無論哪一端都可以擷取到輸入資料流、輸出資料流。
    OutputStream send_stream = client_socket.getOutputStream();   //用戶端擷取輸出資料流InputStream recv_stream = server_socket.getInputStream();
  5. 服務端應主動關閉已串連通訊端,至於監聽通訊端則在合適的地方關閉。
  6. 服務端應該迴圈不斷地負責接收。

簡單的Client端:

import java.io.IOException;import java.io.OutputStream;import java.net.Socket;public class TCPClient {    public static void main(String[] args) {        // 1.建立用戶端通訊端        Socket c_sock = null;        OutputStream client_outstream = null;        try {            c_sock = new Socket("192.168.0.124",8888);            // 2.擷取輸出資料流            client_outstream = c_sock.getOutputStream();            // 3.輸出資料            client_outstream.write("Hello,i'm coming".getBytes());        } catch (IOException e) {            e.printStackTrace();        } finally {            if(c_sock != null){                try{                    c_sock.close();                } catch(IOException e) {                    e.printStackTrace();                }            }        }    }}

簡單的Server端:

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;public class TCPServer {    public static void main(String[] args) {        // 1.建立監聽通訊端        ServerSocket listen_sock = null;        try {            listen_sock = new ServerSocket(8888);        } catch(IOException i) {            i.printStackTrace();        }        Socket server_sock = null;        InputStream in_sock = null;        while (true) {            try {                // 2.和用戶端建立串連,產生已串連通訊端,並擷取用戶端ip地址                server_sock = listen_sock.accept();                String client_ip = server_sock.getInetAddress().getHostAddress();                System.out.println("Client:  " + client_ip + "  connected");                // 3.根據已串連通訊端,擷取輸入資料流,讀取用戶端發送的資料                in_sock = server_sock.getInputStream();                BufferedReader bufr = new BufferedReader(new InputStreamReader(in_sock));                String line = null;                while ((line = bufr.readLine()) != null) {                    System.out.println(line);                }                // 4.關閉已串連通訊端                server_sock.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

以下是tcp實現檔案上傳功能:

  1. 用戶端除了通訊端的輸出資料流,還有讀取本地檔案的輸入資料流,還有通訊端的輸入資料流來讀取來自服務端的反饋資訊。
  2. 服務端也同樣有三流:通訊端的輸入、輸出資料流,寫入上傳目標檔案的輸出資料流。
  3. 用戶端讀取本地檔案的所有資料後,需要使用通訊端的shutdownOutput()來通知服務端通訊端的輸出資料流已到末尾。
  4. 服務端為了能為多人提供上傳功能,需要使用多線程實現並發串連。

Client端:

import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;public class UploadClient {    public static void main(String[] args) {        // TODO Auto-generated method stub        String server_addr = "192.168.0.124";        int server_port = 8888;        Socket send_sock = null;        FileInputStream local_read = null;        try {            // 1.用戶端通訊端            send_sock = new Socket(server_addr, server_port);            // 2.擷取串連管道的輸出資料流            OutputStream send_stream = send_sock.getOutputStream();            // 3.位元組輸入資料流讀取本地檔案資料,並使用通訊端的輸出資料流發送出去            local_read = new FileInputStream("d:/myjava/net/SQL.docx");            byte[] buf = new byte[1024];            int len = 0;            while ((len = local_read.read(buf)) != -1) {                send_stream.write(buf, 0, len);            }            // 4.標記輸出資料流到結尾            send_sock.shutdownOutput();            // 5.接收服務端的反饋資料,如上傳成功,上傳失敗等            InputStream recv_stream = send_sock.getInputStream();            BufferedReader ack_recv = new BufferedReader(new InputStreamReader(recv_stream));            String line = null;            while ((line = ack_recv.readLine()) != null) {                System.out.println(line);            }        } catch (IOException i) {            i.printStackTrace();        } finally {            if (send_sock != null) {                try {                    send_sock.close();                    local_read.close();                } catch (IOException i1) {                    i1.printStackTrace();                }            }            if (local_read != null) {                try {                    local_read.close();                } catch (IOException i2) {                    i2.printStackTrace();                }            }        }    }}

Server端:

import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class UploadServer {    public static void main(String[] args) throws IOException {        ServerSocket listen_sock = new ServerSocket(8888);   //監聽通訊端只需建立一個,因此在任務之外        while (true) {   //每建立一個串連,就開啟一個線程            Socket conn_sock = listen_sock.accept();  //沒有新串連進來時,main主線程阻塞在此            new Thread(new Uploader(conn_sock)).start();        }    }}class Uploader implements Runnable {    private File dest_dir = new File("d:/temp"); // 上傳目錄    private Socket conn_sock = null; // 串連通訊端    InputStream recv_stream = null;    FileOutputStream dest_stream = null;    Uploader(Socket conn_sock) throws IOException {        this.conn_sock = conn_sock;    }    public void run() {        try {            if (!dest_dir.exists()) {                dest_dir.mkdirs();            }            // 1.擷取串連管道的輸入資料流            recv_stream = conn_sock.getInputStream();            // 用戶端ip            String client_ip = conn_sock.getInetAddress().getHostAddress();            System.out.println(client_ip + ".....connected");            // 2.檔案的上傳位置,即輸出目標,以ip命名。如果檔案已存在,則使用括弧加數字建立檔案,如"192.168.100.23(1).txt"            File dest_file = new File(dest_dir, client_ip + ".docx");            int count = 1;            while (dest_file.exists()) {                dest_file = new File(dest_dir, client_ip + "(" + count + ")" + ".docx");                count++;            }            // 3.讀取資料並寫入目標檔案            dest_stream = new FileOutputStream(dest_file);            byte[] buf = new byte[1024];            int len = 0;            while ((len = recv_stream.read(buf)) != -1) {                dest_stream.write(buf, 0, len);            }            // 4. 向用戶端反饋資訊            OutputStream ack_send = conn_sock.getOutputStream();            byte[] text = "upload successful!".getBytes();            ack_send.write(text);        } catch (IOException e1) {            e1.printStackTrace();        } finally {            if (dest_stream != null) {                try {                    dest_stream.close();                } catch (IOException i) {                    i.printStackTrace();                }            }            if (conn_sock != null) {                try {                    conn_sock.close();                } catch (IOException i) {                    i.printStackTrace();                }            }        }    }}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

Tags Index: