Java API —— 網絡編程

一、網絡編程概述
    1)網絡編程概述
    · 計算機網絡
        是指將地理位置不一樣的具備獨立功能的多臺計算機及其外部設備,經過通訊線路鏈接起來,在網絡操做系統,網絡管理軟件及網絡通訊協議的管理和協調下,實現資源共享和信息傳遞的計算機系統。
    · 網絡編程
        就是用來實現網絡互連的不一樣計算機上運行的程序間能夠進行數據交換。
    2)網絡模型
    · 計算機網絡之間以何種規則進行通訊,就是網絡模型研究問題。
    · 網絡模型通常是指
        · OSI(Open System Interconnection開放系統互連)參考模型
        · TCP/IP參考模型
    3)網絡參考模型圖
 
二、網絡編程三要素
    1)IP地址:InetAddress
    網絡中設備的標識,不易記憶,可用主機名
    2)端口號
    用於標識進程的邏輯地址,不一樣進程的標識
    3)傳輸協議
  通信的規則,常見協議:TCP,UDP
    UDP:將數據源和目的封裝成數據包中,不須要創建鏈接;每一個數據報的大小在限制在64k;因無鏈接,是不可靠協議;不須要創建鏈接,速度快
    TCP:創建鏈接,造成傳輸數據的通道;在鏈接中進行大數據量傳輸;經過三次握手完成鏈接,是可靠協議;必須創建鏈接,效率會稍低
    4)InetAddress類的使用
        · 獲取任意主機:public static InetAddress getByName(String host):根據主機名或者IP地址的字符串表示獲得IP地址對象
    · 主機名:getHostName
    · 主機IP地址:getHostAddress         
package netcoding;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
 * Created by gao on 16-1-14.
 */
/*
 * 若是一個類沒有構造方法:
 * A:成員所有是靜態的(Math,Arrays,Collections)
 * B:單例設計模式(Runtime)
 * C:類中有靜態方法返回該類的對象(InetAddress)
 *         class Demo {
 *             private Demo(){}
 *
 *             public static Demo getXxx() {
 *                 return new Demo();
 *             }
 *         }
 *
 * 看InetAddress的成員方法:
 * public static InetAddress getByName(String host):根據主機名或者IP地址的字符串表示獲得IP地址對象
 */
public class NetDemo01 {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress address = InetAddress.getByName("shlgao84");
        String name = address.getHostName();
        String ip = address.getHostAddress();
        System.out.println(name + "---" + ip);
    }
}
 
5)端口號
        · 物理端口 網卡口
        · 邏輯端口 咱們指的就是邏輯端口
    A:每一個網絡程序都會至少有一個邏輯端口
    B:用於標識進程的邏輯地址,不一樣進程的標識
    C:有效端口:0~65535,其中0~1024系統使用或保留端口。
 
三、Socket
    1)Socket套接字:網絡上具備惟一標識的IP地址和端口號組合在一塊兒才能構成惟一能識別的標識符套接字。
    2)Socket原理機制:通訊的兩端都有Socket。網絡通訊其實就是Socket間的通訊。數據在兩個Socket間經過IO傳輸。
 
四、UDP傳輸
    · DatagramSocket與DatagramPacket
    · 創建發送端,接收端。
    · 創建數據包。
    · 調用Socket的發送接收方法。
    · 關閉Socket。
    · 發送端與接收端是兩個獨立的運行程序。
    1)UDP傳輸-發送端思路
        A:創建udp的socket服務
        B:將要發送的數據封裝成數據包
        C:經過udp的socket服務,將數據包發送出
        D:關閉資源
    2)UDP傳輸-接收端思路
        A:創建udp的socket服務.
        B:經過receive方法接收數據
        C:將收到的數據存儲到數據包對象中
        D:經過數據包對象的功能來完成對接收到數據進行解析.
        E:能夠對資源進行關閉
例子1:發送端
package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
public class SendDemo01 {
    public static void main(String[] args) throws IOException {
        // 建立發送端Socket對象
        // DatagramSocket()
        DatagramSocket ds = new DatagramSocket();
        // 建立數據,並把數據打包
        // DatagramPacket(byte[] buf, int length, InetAddress address, int port)
        // 建立數據
        byte[] bys = "hello,udp,我來了".getBytes();
        // 長度
        int len = bys.length;
        // IP地址對象
        InetAddress address = InetAddress.getByName("10.130.26.23");
        // 端口
        int port = 10086;
        DatagramPacket dp = new DatagramPacket(bys,len,address,port);
        // 調用Socket對象的發送方法發送數據包
        // public void send(DatagramPacket p)
        ds.send(dp);
        // 釋放資源
        ds.close();
    }
}

接收端:java

package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
public class ReceiveDemo01 {
    public static void main(String[] args) throws IOException {
        // 建立接收端Socket對象
        // DatagramSocket(int port)
        DatagramSocket ds = new DatagramSocket(10086);
        // 建立一個數據包(接收容器)
        // DatagramPacket(byte[] buf, int length)
        byte[] bys = new byte[1024];
        int length = bys.length;
        DatagramPacket dp = new DatagramPacket(bys, length);
        // 調用Socket對象的接收方法接收數據
        ds.receive(dp);// 阻塞式
        // 解析數據包,並顯示在控制檯
        // 獲取對方的ip
        // public InetAddress getAddress()
        InetAddress address = dp.getAddress();
        String ip = address.getHostAddress();
        // public byte[] getData():獲取數據緩衝區
        // public int getLength():獲取數據的實際長度
        byte[] bys2 = dp.getData();
        int len = dp.getLength();
        String s = new String(bys2, 0, len);
        System.out.println(ip + "傳遞的數據是:" + s);
        // 釋放資源
        ds.close();
    }
}

例子2:發送端(優化代碼)apache

package netcoding;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
/*
* 數據來自於鍵盤錄入
* 鍵盤錄入數據要本身控制錄入結束。
*/
public class SendDemo02 {
    public static void main(String[] args) throws IOException {
        // 建立發送端的Socket對象
        DatagramSocket ds = new DatagramSocket();
        // 封裝鍵盤錄入數據
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while ((line = br.readLine())!= null) {
            if ("886".equals(line)){
                break;
            }
            // 建立數據並打包
            byte[] bys = line.getBytes();
            DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("10.130.26.23"), 12345);
            //DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("10.130.26.255"), 10086);
            // 發送數據
            ds.send(dp);
        }
        // 釋放資源
        ds.close();
    }
}

接收端:編程

package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
 * Created by gao on 16-1-18.
 */
/*
 * 屢次啓動接收端:
 * java.net.BindException: Address already in use: Cannot bind
 * 端口被佔用。
 */
public class ReceiveDemo02 {
    public static void main(String[] args) throws IOException {
        // 建立接收端的Socket對象
        DatagramSocket ds = new DatagramSocket(12345);
        while (true) {
            // 建立一個包裹
            byte[] bys = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bys, bys.length);
            // 接收數據
            ds.receive(dp);
            // 解析數據
            String ip = dp.getAddress().getHostAddress();
            String s = new String(dp.getData(), 0, dp.getLength());
            System.out.println("from:" + ip + " data is:" + s);
        }
        // 釋放資源
        // 接收端應該一直開着等待接收數據,是不須要關閉
        // ds.close();
    }
}
例子3:(多線程實現聊天室程序)
主函數:
package netcoding;
import java.io.IOException;
import java.net.DatagramSocket;
/**
 * Created by gao on 16-1-18.
 */
public class ChatRoom {
    public static void main(String[] args) throws IOException {
        DatagramSocket dsSend = new DatagramSocket();
        DatagramSocket dsReceive = new DatagramSocket(12306);
        SendThread st = new SendThread(dsSend);
        ReceiveThread rt = new ReceiveThread(dsReceive);
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(rt);
        t1.start();
        t2.start();
    }
}

 發送線程:設計模式

package netcoding;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
 * Created by gao on 16-1-18.
 */
public class SendThread implements Runnable {
    private DatagramSocket ds;
    public SendThread(DatagramSocket ds) {
        this.ds = ds;
    }
    @Override
    public void run() {
        try {
            // 封裝鍵盤錄入數據
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    System.in));
            String line = null;
            while ((line = br.readLine()) != null) {
                if ("886".equals(line)) {
                    break;
                }
                // 建立數據並打包
                byte[] bys = line.getBytes();
                // DatagramPacket dp = new DatagramPacket(bys, bys.length,
                // InetAddress.getByName("192.168.12.92"), 12345);
                DatagramPacket dp = new DatagramPacket(bys, bys.length,
                        InetAddress.getByName("10.130.26.23"), 12306);
                // 發送數據
                ds.send(dp);
            }
            // 釋放資源
            ds.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

接收線程:服務器

package netcoding;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
 * Created by gao on 16-1-18.
 */
public class ReceiveThread implements Runnable{
    private DatagramSocket ds;
    public ReceiveThread(DatagramSocket ds) {
        this.ds = ds;
    }
    @Override
    public void run() {
        try {
            while (true) {
                // 建立一個包裹
                byte[] bys = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bys, bys.length);
                // 接收數據
                ds.receive(dp);
                // 解析數據
                String ip = dp.getAddress().getHostAddress();
                String s = new String(dp.getData(), 0, dp.getLength());
                System.out.println("from " + ip + " data is : " + s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 
五、TCP傳輸
    · Socket和ServerSocket
    · 創建客戶端和服務器端
    · 創建鏈接後,經過Socket中的IO流進行數據的傳輸
    · 關閉socket
    · 一樣,客戶端與服務器端是兩個獨立的應用程序。
    1)TCP傳輸-客戶端思路

  A:創建客戶端的Socket服務,並明確要鏈接的服務器。
  B:若是鏈接創建成功,就代表,已經創建了數據傳輸的通道.就能夠在該通道經過IO進行數據的讀取和寫入.該通道稱爲Socket流,Socket流中既有讀取流,也有寫入流.
  C:經過Socket對象的方法,能夠獲取這兩個流
  D:經過流的對象能夠對數據進行傳輸
  E:若是傳輸數據完畢,關閉資源網絡

    2)TCP傳輸-服務器端思路
        A:創建服務器端的socket服務,須要一個端口
        B:服務端沒有直接流的操做,而是經過accept方法獲取客戶端對象,在經過獲取到的客戶端對象的流和客戶端進行通訊
        C:經過客戶端的獲取流對象的方法,讀取數據或者寫入數據
        D:若是服務完成,須要關閉客戶端,而後關閉服務器,可是,通常會關閉客戶端,不會關閉服務器,由於服務端是一直提供服務的
 
例子1:
服務器:
package netcoding;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
/*
 * TCP協議接收數據:
 * A:建立接收端的Socket對象
 * B:監聽客戶端鏈接。返回一個對應的Socket對象
 * C:獲取輸入流,讀取數據顯示在控制檯
 * D:釋放資源
 */
public class ServerDemo01 {
    public static void main(String[] args) throws IOException {
        // 建立接收端的Socket對象
        // ServerSocket(int port)
        ServerSocket ss = new ServerSocket(12306);
        // 監聽客戶端鏈接。返回一個對應的Socket對象
        // public Socket accept()
        Socket s = ss.accept();  // 偵聽並接受到此套接字的鏈接。此方法在鏈接傳入以前一直阻塞。
        // 獲取輸入流,讀取數據顯示在控制檯
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys);  // 阻塞式方法
        String str = new String(bys, 0, len);
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "---" + str);
        // 釋放資源
        s.close();
        // ss.close(); //這個不該該關閉
    }
}

客戶端:多線程

package netcoding;
import com.sun.org.apache.xml.internal.serializer.OutputPropertyUtils;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
/*
 * TCP協議發送數據:
 * A:建立發送端的Socket對象
 *         這一步若是成功,就說明鏈接已經創建成功了。
 * B:獲取輸出流,寫數據
 * C:釋放資源
 *
 * 鏈接被拒絕。TCP協議必定要先看服務器。
 * java.net.ConnectException: Connection refused: connect
 */
public class ClientDemo01 {
    public static void main(String[] args) throws IOException{
        // 建立發送端的Socket對象
        // Socket(InetAddress address, int port)
        // Socket(String host, int port)
        // Socket s = new Socket(InetAddress.getByName("192.168.12.92"), 8888);
        Socket s = new Socket("10.130.26.23",12306);
        // 獲取輸出流,寫數據
        // public OutputStream getOutputStream()
        OutputStream os = s.getOutputStream();
        os.write("hello tcp.".getBytes());
        // 釋放資源
        s.close();
    }
}
例子2: 服務器給客戶端反饋
服務器
package netcoding;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
public class ServerDemo02 {
    public static void main(String[] args) throws IOException {
        // 建立服務器Socket對象
        ServerSocket ss = new ServerSocket(12306);
        // 監聽客戶端的鏈接
        Socket s = ss.accept(); // 阻塞
        // 獲取輸入流
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys); // 阻塞
        String server = new String(bys, 0, len);
        System.out.println("server:" + server);
        // 獲取輸出流
        OutputStream os = s.getOutputStream();
        os.write("數據已經收到".getBytes());
        // 釋放資源
        s.close();
        // ss.close();
    }
}

 客戶端socket

package netcoding;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
 * Created by gao on 16-1-18.
 */
public class ClientDemo02 {
    public static void main(String[] args) throws IOException {
        // 建立客戶端Socket對象
        Socket s = new Socket("10.130.26.23", 12306);
        // 獲取輸出流
        OutputStream os = s.getOutputStream();
        os.write("ClientDemo02".getBytes());
        // 獲取輸入流
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len = is.read(bys); // 阻塞
        String client = new String(bys, 0, len);
        System.out.println("client:" + client);
        // 釋放資源
        s.close();
    }
}
例子3:客戶端鍵盤錄入,服務器輸出到控制檯
服務器
package cn.itcast_08;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 建立服務器Socket對象
        ServerSocket ss = new ServerSocket(22222);
        // 監聽客戶端鏈接
        Socket s = ss.accept();
        // 包裝通道內容的流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        // br.close();
        s.close();
        // ss.close();
    }
}

 客戶端tcp

package cn.itcast_08;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
 * 客戶端鍵盤錄入,服務器輸出到控制檯
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 建立客戶端Socket對象
        Socket s = new Socket("192.168.12.92", 22222);
        // 鍵盤錄入數據
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 把通道內的流給包裝一下
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            // 鍵盤錄入數據要自定義結束標記
            if ("886".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 釋放資源
        // bw.close();
        // br.close();
        s.close();
    }
}
例子4:客戶端鍵盤錄入,服務器輸出文本文件
服務器端:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 建立服務器Socket對象
        ServerSocket ss = new ServerSocket(23456);
        // 監聽客戶端鏈接
        Socket s = ss.accept();
        // 封裝通道內的數據
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        // 封裝文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        // br.close();
        s.close();
        // ss.close();
    }
}

 客戶端:ide

package cn.itcast_09;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
 * 客戶端鍵盤錄入,服務器輸出文本文件
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 建立客戶端Socket對象
        Socket s = new Socket("192.168.12.92", 23456);
        // 封裝鍵盤錄入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 封裝通道內的數據
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            if ("over".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // bw.close();
        // br.close();
        s.close();
    }
}

例子5:客戶端文本文件,服務器輸出到控制檯

服務器端:
package cn.itcast_10;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 建立服務器Socket對象
        ServerSocket ss = new ServerSocket(34567);
        // 監聽客戶端鏈接
        Socket s = ss.accept();
        // 封裝通道內的流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        s.close();
    }
}

 客戶端:

package cn.itcast_10;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
 * 客戶端文本文件,服務器輸出到控制檯
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 建立Socket對象
        Socket s = new Socket("192.168.12.92", 34567);
        // 封裝文本文件
        BufferedReader br = new BufferedReader(new FileReader(
                "InetAddressDemo.java"));
        // 封裝通道內的流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        br.close();
        s.close();
    }
}
例子6:客戶端文本文件,服務器輸出文本文件
服務器端:
package cn.itcast_12;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
    public static void main(String[] args) throws IOException {
        // 建立服務器端的Socket對象
        ServerSocket ss = new ServerSocket(11111);
        // 監聽客戶端鏈接
        Socket s = ss.accept();// 阻塞
        // 封裝通道內的流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        // 封裝文本文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
        String line = null;
        while ((line = br.readLine()) != null) { // 阻塞
        // if("over".equals(line)){
        // break;
        // }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // 給出反饋
        BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        bwServer.write("文件上傳成功");
        bwServer.newLine();
        bwServer.flush();
        // 釋放資源
        bw.close();
        s.close();
    }
}

 客戶端:

package cn.itcast_12;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
 * 按照咱們正常的思路加入反饋信息,結果卻沒反應。爲何呢?
 * 讀取文本文件是能夠以null做爲結束信息的,可是呢,通道內是不能這樣結束信息的。
 * 因此,服務器根本就不知道你結束了。而你還想服務器給你反饋。因此,就相互等待了。
 * 
 * 如何解決呢?
 * A:在多寫一條數據,告訴服務器,讀取到這條數聽說明我就結束,你也結束吧。
 *         這樣作能夠解決問題,可是很差。
 * B:Socket對象提供了一種解決方案
 *         public void shutdownOutput()
 */
public class UploadClient {
    public static void main(String[] args) throws IOException {
        // 建立客戶端Socket對象
        Socket s = new Socket("192.168.12.92", 11111);
        // 封裝文本文件
        BufferedReader br = new BufferedReader(new FileReader(
                "InetAddressDemo.java"));
        // 封裝通道內流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) { // 阻塞
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        
        //自定義一個結束標記
//        bw.write("over");
//        bw.newLine();
//        bw.flush();
        
        //Socket提供了一個終止,它會通知服務器你別等了,我沒有數據過來了
        s.shutdownOutput();
        // 接收反饋
        BufferedReader brClient = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String client = brClient.readLine(); // 阻塞
        System.out.println(client);
        // 釋放資源
        br.close();
        s.close();
    }
}
例子7:上傳圖片案例
服務器端:
package cn.itcast_13;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
    public static void main(String[] args) throws IOException {
        // 建立服務器Socket對象
        ServerSocket ss = new ServerSocket(19191);
        // 監聽客戶端鏈接
        Socket s = ss.accept();
        // 封裝通道內流
        BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
        // 封裝圖片文件
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream("mn.jpg"));
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
            bos.flush();
        }
        // 給一個反饋
        OutputStream os = s.getOutputStream();
        os.write("圖片上傳成功".getBytes());
        bos.close();
        s.close();
    }
}

 客戶端:

package cn.itcast_13;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class UploadClient {
    public static void main(String[] args) throws IOException {
        // 建立客戶端Socket對象
        Socket s = new Socket("192.168.12.92", 19191);
        // 封裝圖片文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                "林青霞.jpg"));
        // 封裝通道內的流
        BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
            bos.flush();
        }
        
        s.shutdownOutput();
        // 讀取反饋
        InputStream is = s.getInputStream();
        byte[] bys2 = new byte[1024];
        int len2 = is.read(bys2);
        String client = new String(bys2, 0, len2);
        System.out.println(client);
        // 釋放資源
        bis.close();
        s.close();
    }
}
例子8:服務器的代碼用線程進行封裝,這樣能夠模擬一個同時接收多人上傳文件的服務器。(用循環也能夠可是效率低,是單線程的程序)
服務器線程:
package cn.itcast_15;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class UserThread implements Runnable {
    private Socket s;
    public UserThread(Socket s) {
        this.s = s;
    }
    @Override
    public void run() {
        try {
            // 封裝通道內的流
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    s.getInputStream()));
            // 封裝文本文件
            // BufferedWriter bw = new BufferedWriter(new
            // FileWriter("Copy.java"));
            // 爲了防止名稱衝突
            String newName = System.currentTimeMillis() + ".java";
            BufferedWriter bw = new BufferedWriter(new FileWriter(newName));
            String line = null;
            while ((line = br.readLine()) != null) { // 阻塞
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            // 給出反饋
            BufferedWriter bwServer = new BufferedWriter(
                    new OutputStreamWriter(s.getOutputStream()));
            bwServer.write("文件上傳成功");
            bwServer.newLine();
            bwServer.flush();
            // 釋放資源
            bw.close();
            s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 服務器端:

package cn.itcast_15;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
    public static void main(String[] args) throws IOException {
        // 建立服務器Socket對象
        ServerSocket ss = new ServerSocket(11111);
        while (true) {
            Socket s = ss.accept();
            new Thread(new UserThread(s)).start();
        }
    }
}

客戶端:

package cn.itcast_15;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class UploadClient {
    public static void main(String[] args) throws IOException {
        // 建立客戶端Socket對象
        Socket s = new Socket("192.168.12.92", 11111);
        // 封裝文本文件
        // BufferedReader br = new BufferedReader(new FileReader(
        // "InetAddressDemo.java"));
        BufferedReader br = new BufferedReader(new FileReader(
                "ReceiveDemo.java"));
        // 封裝通道內流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                s.getOutputStream()));
        String line = null;
        while ((line = br.readLine()) != null) { // 阻塞
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        // Socket提供了一個終止,它會通知服務器你別等了,我沒有數據過來了
        s.shutdownOutput();
        // 接收反饋
        BufferedReader brClient = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String client = brClient.readLine(); // 阻塞
        System.out.println(client);
        // 釋放資源
        br.close();
        s.close();
    }
}
        
相關文章
相關標籤/搜索