Java 網絡編程

網絡編程html

網絡模型
 OSI參考模型
  //應用層 表示層 會話層 傳輸層 網絡層 數據鏈路層 物理層
 TCP/IP參考模型
  //應用層 傳輸層 網際層 網絡接口層
網絡通信要素
 IP地址
  //網絡中設備的標識 本地迴環地址 127.0.0.1 主機名 localhost
 端口號
  //標識進程的邏輯地址 有效端口 0~65535 其中0~1024系統使用或保留端口
 傳輸協議
  //通信的規則 TCP UDP
UDP
 將數據及源和目的 封裝成數據包中 不須要創建鏈接
 每一個數據包的大小限制在64K內
 因無鏈接 是不可靠協議
 不須要創建鏈接 速度快
TCP
 創建鏈接 造成傳輸數據的通道
 在鏈接中進行大數據量傳輸
 經過三次握手完成鏈接 是可靠協議
 必須創建鏈接 效率會稍低
java

InetAddress //IP地址
 getLocalHost //獲取本地地址IP對象
 getHostAddress //IP地址字符串
 getHostName //IP主機名
web

public class IPDemo {

    public static void main(String[] args) throws UnknownHostException {

        //獲取本地主機ip地址對象。 
        InetAddress ip = InetAddress.getLocalHost();
        
        //獲取其餘主機的ip地址對象。
        ip = InetAddress.getByName("192.168.1.110");//InetAddress.getByName("my_think");
        
        System.out.println(ip.getHostAddress());
        System.out.println(ip.getHostName());
    }

}

Socket  編程

  Socket就是爲網絡服務提供的一種機制  瀏覽器

  通訊的兩端都有Socket  tomcat

  網絡通訊其實就是Socket間的通訊  服務器

  數據在兩個Socket間經過IO傳輸網絡

UDP傳輸  多線程

  DatagramSocket與DatagramPacket  app

  創建發送端 接收端  創建數據包  調用Socket的發送接收方法  

  關閉Socket  

  發送端與接收端是兩個獨立的運行程序

public class UDPSendDemo {

    public static void main(String[] args) throws IOException {

        System.out.println("發送端啓動......");
        /*
         * 建立UDP傳輸的發送端。
         * 思路:
         * 1,創建udp的socket服務。
         * 2,將要發送的數據封裝到數據包中。 
         * 3,經過udp的socket服務將數據包發送出去。
         * 4,關閉socket服務。
         */
        //1,udpsocket服務。使用DatagramSocket對象。
        DatagramSocket ds = new DatagramSocket(8888);
        
        //2,將要發送的數據封裝到數據包中。
        String str = "udp傳輸演示:哥們來了!";
            //使用DatagramPacket將數據封裝到的該對象包中。
        byte[] buf = str.getBytes();
        
        DatagramPacket dp = 
                new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10000);
        
        
        //3,經過udp的socket服務將數據包發送出去。使用send方法。
        ds.send(dp);
        
        //4,關閉資源。
        ds.close();
        
        
    }

}
public class UDPReceDemo {

    public static void main(String[] args) throws IOException {

        System.out.println("接收端啓動......");
        /*
         * 創建UDP接收端的思路。
         * 1,創建udp socket服務,由於是要接收數據,必需要明確一個端口號。
         * 2,建立數據包,用於存儲接收到的數據。方便用數據包對象的方法解析這些數據.
         * 3,使用socket服務的receive方法將接收的數據存儲到數據包中。
         * 4,經過數據包的方法解析數據包中的數據。
         * 5,關閉資源 
         */
        
        //1,創建udp socket服務。
        DatagramSocket ds = new DatagramSocket(10000);
        
        
        //2,建立數據包。
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        
        //3,使用接收方法將數據存儲到數據包中。
        ds.receive(dp);//阻塞式的。
        
        //4,經過數據包對象的方法,解析其中的數據,好比,地址,端口,數據內容。
        String ip = dp.getAddress().getHostAddress();
        int port = dp.getPort();
        String text = new String(dp.getData(),0,dp.getLength());
        
        System.out.println(ip+":"+port+":"+text);
        
        //5,關閉資源。
        ds.close();
        
        
    }
    

}

升級版

public class UDPSendDemo2 {

    public static void main(String[] args) throws IOException {

        System.out.println("發送端啓動......");
        /*
         * 建立UDP傳輸的發送端。
         * 思路:
         * 1,創建udp的socket服務。
         * 2,將要發送的數據封裝到數據包中。 
         * 3,經過udp的socket服務將數據包發送出去。
         * 4,關閉socket服務。
         */
        //1,udpsocket服務。使用DatagramSocket對象。
        DatagramSocket ds = new DatagramSocket(8888);
        
        
//        String str = "udp傳輸演示:哥們來了!";
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        
        while((line=bufr.readLine())!=null){
            
            
            byte[] buf = line.getBytes();
            DatagramPacket dp = 
                    new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10000);
            ds.send(dp);
            
            if("886".equals(line))
                break;
        }
        
        //4,關閉資源。
        ds.close();
        
        
    }

}
public class UDPReceDemo2 {

    public static void main(String[] args) throws IOException {

        System.out.println("接收端啓動......");
        /*
         * 創建UDP接收端的思路。
         * 1,創建udp socket服務,由於是要接收數據,必需要明確一個端口號。
         * 2,建立數據包,用於存儲接收到的數據。方便用數據包對象的方法解析這些數據.
         * 3,使用socket服務的receive方法將接收的數據存儲到數據包中。
         * 4,經過數據包的方法解析數據包中的數據。
         * 5,關閉資源 
         */
        
        //1,創建udp socket服務。
        DatagramSocket ds = new DatagramSocket(10000);
        
        while(true){
        
        //2,建立數據包。
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        
        //3,使用接收方法將數據存儲到數據包中。
        ds.receive(dp);//阻塞式的。
        
        //4,經過數據包對象的方法,解析其中的數據,好比,地址,端口,數據內容。
        String ip = dp.getAddress().getHostAddress();
        int port = dp.getPort();
        String text = new String(dp.getData(),0,dp.getLength());
        
        System.out.println(ip+":"+port+":"+text);
        
        
        }
        //5,關閉資源。
//        ds.close();
        
        
    }
    
}

聊天室

public class ChatDemo {

    public static void main(String[] args) throws IOException {

        
        DatagramSocket send = new DatagramSocket();
        
        DatagramSocket rece = new DatagramSocket(10001);
        new Thread(new Send(send)).start();
        new Thread(new Rece(rece)).start();
        
    }

}
public class Send implements Runnable {

    private DatagramSocket ds;
    
    public Send(DatagramSocket ds){
        this.ds = ds;
    }
    
    @Override
    public void run() {
        
        try {
            BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            
            while((line=bufr.readLine())!=null){
                
                
                byte[] buf = line.getBytes();
                DatagramPacket dp = 
                        new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10001);
                ds.send(dp);
                
                if("886".equals(line))
                    break;
            }
            
            ds.close();
        } catch (Exception e) {
        }
    }

}
public class Rece implements Runnable {

    private DatagramSocket ds;

    public Rece(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    public void run() {
        try {
            while (true) {

                // 2,建立數據包。
                byte[] buf = new byte[1024];
                DatagramPacket dp = new DatagramPacket(buf, buf.length);

                // 3,使用接收方法將數據存儲到數據包中。
                ds.receive(dp);// 阻塞式的。

                // 4,經過數據包對象的方法,解析其中的數據,好比,地址,端口,數據內容。
                String ip = dp.getAddress().getHostAddress();
                int port = dp.getPort();
                String text = new String(dp.getData(), 0, dp.getLength());
                
                System.out.println(ip + "::" + text);
                if(text.equals("886")){
                    System.out.println(ip+"....退出聊天室");
                }

            }
        } catch (Exception e) {

        }

    }

}

TCP傳輸
   Socket和ServerSocket
   創建客戶端和服務器端
   創建鏈接後 經過Socket中的IO流進行數據傳輸

public class ServerDemo {

    public static void main(String[] args) throws IOException {
//        服務端接收客戶端發送過來的數據,並打印在控制檯上。 
        /*
         * 創建tcp服務端的思路:
         * 1,建立服務端socket服務。經過ServerSocket對象。
         * 2,服務端必須對外提供一個端口,不然客戶端沒法鏈接。
         * 3,獲取鏈接過來的客戶端對象。
         * 4,經過客戶端對象獲取socket流讀取客戶端發來的數據 
         *         並打印在控制檯上。
         * 5,關閉資源。關客戶端,關服務端。 
         */
        
        //1建立服務端對象。
        ServerSocket ss = new ServerSocket(10002);
        
        //2,獲取鏈接過來的客戶端對象。
        Socket s = ss.accept();//阻塞式.
        
        String ip = s.getInetAddress().getHostAddress();
        
        //3,經過socket對象獲取輸入流,要讀取客戶端發來的數據
        InputStream in = s.getInputStream();
        
        byte[] buf = new byte[1024];
        
        int len = in.read(buf);
        String text = new String(buf,0,len);
        System.out.println(ip+":"+text);

                
        s.close();
        ss.close();
        
    }

}
public class ClientDemo {

    public static void main(String[] args) throws UnknownHostException, IOException {
        //客戶端發數據到服務端
        /*
         * Tcp傳輸,客戶端創建的過程。
         * 1,建立tcp客戶端socket服務。使用的是Socket對象。
         *         建議該對象一建立就明確目的地。要鏈接的主機。 
         * 2,若是鏈接創建成功,說明數據傳輸通道已創建。
         *         該通道就是socket流 ,是底層創建好的。 既然是流,說明這裏既有輸入,又有輸出。
         *         想要輸入或者輸出流對象,能夠找Socket來獲取。 
         *         能夠經過getOutputStream(),和getInputStream()來獲取兩個字節流。
         * 3,使用輸出流,將數據寫出。 
         * 4,關閉資源。 
         */
        
        
        //建立客戶端socket服務。
        Socket socket = new Socket("192.168.1.100",10002);
        
        //獲取socket流中的輸出流。 
        OutputStream out = socket.getOutputStream();
        
        
        //使用輸出流將指定的數據寫出去。
        out.write("tcp演示:哥們又來了!".getBytes());
        
        //關閉資源。
        socket.close();
                
    }

}

升級版

public class ServerDemo2 {

    public static void main(String[] args) throws IOException {
//        服務端接收客戶端發送過來的數據,並打印在控制檯上。 
        /*
         * 創建tcp服務端的思路:
         * 1,建立服務端socket服務。經過ServerSocket對象。
         * 2,服務端必須對外提供一個端口,不然客戶端沒法鏈接。
         * 3,獲取鏈接過來的客戶端對象。
         * 4,經過客戶端對象獲取socket流讀取客戶端發來的數據 
         *         並打印在控制檯上。
         * 5,關閉資源。關客戶端,關服務端。 
         */
        
        //1建立服務端對象。
        ServerSocket ss = new ServerSocket(10002);
        
        //2,獲取鏈接過來的客戶端對象。
        Socket s = ss.accept();
        
        String ip = s.getInetAddress().getHostAddress();
        
        //3,經過socket對象獲取輸入流,要讀取客戶端發來的數據
        InputStream in = s.getInputStream();
        
        byte[] buf = new byte[1024];
        
        int len = in.read(buf);
        String text = new String(buf,0,len);
        System.out.println(ip+":"+text);
                
        //使用客戶端socket對象的輸出流給客戶端返回數據
        OutputStream out = s.getOutputStream();
        out.write("收到".getBytes());
        
        s.close();
        ss.close();
        
    }

}
public class ClientDemo2 {

    public static void main(String[] args) throws UnknownHostException, IOException {
        //客戶端發數據到服務端
        /*
         * Tcp傳輸,客戶端創建的過程。
         * 1,建立tcp客戶端socket服務。使用的是Socket對象。
         *         建議該對象一建立就明確目的地。要鏈接的主機。 
         * 2,若是鏈接創建成功,說明數據傳輸通道已創建。
         *         該通道就是socket流 ,是底層創建好的。 既然是流,說明這裏既有輸入,又有輸出。
         *         想要輸入或者輸出流對象,能夠找Socket來獲取。 
         *         能夠經過getOutputStream(),和getInputStream()來獲取兩個字節流。
         * 3,使用輸出流,將數據寫出。 
         * 4,關閉資源。 
         */
        
        
        
        Socket socket = new Socket("192.168.1.100",10002);
        
        OutputStream out = socket.getOutputStream();    
        
        out.write("tcp演示:哥們又來了!".getBytes());
        
        //讀取服務端返回的數據,使用socket讀取流。 
        InputStream in = socket.getInputStream();
        byte[] buf = new byte[1024];
        
        int len = in.read(buf);
        
        String  text = new String(buf,0,len);
        
        System.out.println(text);
        
        //關閉資源。
        socket.close();
        
    }

}

兩個練習Demo
1 將客戶端發送的小寫字母轉換爲大寫字母 輸入over結束
2 上傳文本到服務端

TCP上傳圖片 多線程

public class UploadPicServer {

    public static void main(String[] args) throws IOException {
            
        //建立tcp的socket服務端。
        ServerSocket ss = new ServerSocket(10006);
        
        while(true){
            Socket s = ss.accept();            
            
            new Thread(new UploadTask(s)).start();        
            
        }
        //獲取客戶端。
        
        
//        ss.close();
        
        
    }

}
public class UploadTask implements Runnable {

    private static final int SIZE = 1024*1024*2;
    private Socket s;

    public  UploadTask(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {

        int count = 0;
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + ".....connected");
        
        try{

        // 讀取客戶端發來的數據。
        InputStream in = s.getInputStream();

        // 將讀取到數據存儲到一個文件中。
        File dir = new File("c:\\pic");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File file = new File(dir, ip + ".jpg");
        //若是文件已經存在於服務端 
        while(file.exists()){
            file = new File(dir,ip+"("+(++count)+").jpg");
        }
        
        
        FileOutputStream fos = new FileOutputStream(file);

        byte[] buf = new byte[1024];

        int len = 0;

        while ((len = in.read(buf)) != -1) {
            
            
            
            fos.write(buf, 0, len);
            
            if(file.length()>SIZE){
                System.out.println(ip+"文件體積過大");
                
                fos.close();
                s.close();
                
                
                System.out.println(ip+"...."+file.delete());
                
                return ;
            }
        }

        // 獲取socket輸出流,將上傳成功字樣發給客戶端。
        OutputStream out = s.getOutputStream();
        out.write("上傳成功".getBytes());

        fos.close();
        s.close();
        }catch(IOException e){
            
        }

    }

}
public class UploadPicClient {

    public static void main(String[] args) throws UnknownHostException, IOException {

        
        //1,建立客戶端socket。
        Socket s = new Socket("192.168.1.100",10006);
        
        //2,讀取客戶端要上傳的圖片文件。
        FileInputStream fis = new FileInputStream("c:\\0.bmp");
        
        //3,獲取socket輸出流,將讀到圖片數據發送給服務端。
        OutputStream out = s.getOutputStream();
        
        byte[] buf = new byte[1024];
        
        int len = 0;
        
        while((len=fis.read(buf))!=-1){
            out.write(buf,0,len);
        }
        
        //告訴服務端說:這邊的數據發送完畢。讓服務端中止讀取。
        s.shutdownOutput();
        
        
        //讀取服務端發回的內容。         
        InputStream in  = s.getInputStream();
        byte[] bufIn = new byte[1024];
        
        int lenIn = in.read(buf);
        String text = new String(buf,0,lenIn);
        System.out.println(text);
        
        fis.close();
        s.close();    
        
    }

}

客戶端服務端模型 最多見的客戶端:  瀏覽器 :IE。 最多見的服務端:  服務器:Tomcat。

爲了瞭解其原理:

自定義服務端, 使用已有的客戶端IE,瞭解一下客戶端給服務端發了什麼請求?

發送的請求是:

GET / HTTP/1.1  請求行  請求方式  /myweb/1.html  請求的資源路徑   http協議版本。
請求消息頭 . 屬性名:屬性值
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, 
application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept: */*     
Accept-Language: zh-cn,zu;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)
Host: 192.168.1.100:9090
//Host: www.huyouni.com:9090
Connection: Keep-Alive
//空行
//請求體

服務端發回應答消息

HTTP/1.1 200 OK   //應答行,http的協議版本   應答狀態碼   應答狀態描述信息

應答消息屬性信息。 屬性名:屬性值
Server: Apache-Coyote/1.1
ETag: W/"199-1323480176984"
Last-Modified: Sat, 10 Dec 2011 01:22:56 GMT
Content-Type: text/html
Content-Length: 199
Date: Fri, 11 May 2012 07:51:39 GMT
Connection: close
//空行
//應答體。
<html>
    <head>
        <title>這是個人網頁</title>
    </head>

    <body>

        <h1>歡迎光臨</h1>

        <font size='5' color="red">這是一個tomcat服務器中的資源。是一個html網頁。</font>
    </body>


</html>

Demo

public class MyTomcat {

    public static void main(String[] args) throws IOException {

        ServerSocket ss = new ServerSocket(9090);
        
        Socket s = ss.accept();
        System.out.println(s.getInetAddress().getHostAddress()+".....connected");
        
        InputStream in = s.getInputStream();
        
        byte[] buf = new byte[1024];
        
        int len = in.read(buf);
        String text = new String(buf,0,len);
        System.out.println(text);
        
        
        //給客戶端一個反饋信息。
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
        
        out.println("<font color='red' size='7'>歡迎光臨</font>");
        
        s.close();
        ss.close();
    }

}
public class MyBrowser {

    public static void main(String[] args) throws UnknownHostException, IOException {

        Socket s = new Socket("192.168.1.100",8080);
        
        //模擬瀏覽器,給tomcat服務端發送符合http協議的請求消息。
        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
        out.println("GET /myweb/1.html HTTP/1.1");
        out.println("Accept: */*");
        out.println("Host: 192.168.1.100:8080");
        out.println("Connection: close");
        out.println();
        out.println();
        
        
        InputStream in = s.getInputStream();
        
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        
        String str =new String(buf,0,len);
        System.out.println(str);
        
        s.close();
        
        //http://192.168.1.100:8080/myweb/1.html
    }

}
public class URLDemo {

    public static void main(String[] args) throws IOException {

        String str_url = "http://192.168.1.100:8080/myweb/1.html";
        
        URL url = new URL(str_url);
        
//        System.out.println("getProtocol:"+url.getProtocol());
//        System.out.println("getHost:"+url.getHost());
//        System.out.println("getPort:"+url.getPort());
//        System.out.println("getFile:"+url.getFile());
//        System.out.println("getPath:"+url.getPath());
//        System.out.println("getQuery:"+url.getQuery());
        
//        InputStream in = url.openStream();
        
        //獲取url對象的Url鏈接器對象。將鏈接封裝成了對象:java中內置的能夠解析的具體協議的對象+socket.
        URLConnection conn = url.openConnection();
        
//        String value = conn.getHeaderField("Content-Type");
//        System.out.println(value);
        
//        System.out.println(conn);
        //sun.net.www.protocol.http.HttpURLConnection:http://192.168.1.100:8080/myweb/1.html
        
        InputStream in = conn.getInputStream();
        
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        
        String text = new String(buf,0,len);
        
        System.out.println(text);
        
        in.close();

    }

}

網絡結構

1,C/S  client/server    

  特色:   該結構的軟件,客戶端和服務端都須要編寫。   可發成本較高,維護較爲麻煩。     好處:   客戶端在本地能夠分擔一部分運算。

2,B/S  browser/server  

  特色:   該結構的軟件,只開發服務器端,不開發客戶端,由於客戶端直接由瀏覽器取代。   開發成本相對低,維護更爲簡單。  缺點:全部運算都要在服務端完成。

一個簡單瀏覽器的實現

public class MyBrowseGUI extends javax.swing.JFrame {
    private JTextField url_text;
    private JButton goto_but;
    private JScrollPane jScrollPane1;
    private JTextArea page_content;

    /**
    * Auto-generated main method to display this JFrame
    */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                MyBrowseGUI inst = new MyBrowseGUI();
                inst.setLocationRelativeTo(null);
                inst.setVisible(true);
            }
        });
    }
    
    public MyBrowseGUI() {
        super();
        initGUI();
    }
    
    private void initGUI() {
        try {
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            getContentPane().setLayout(null);
            {
                url_text = new JTextField();
                getContentPane().add(url_text);
                url_text.setBounds(12, 36, 531, 44);
                url_text.addKeyListener(new KeyAdapter() {
                    public void keyPressed(KeyEvent evt) {
                        url_textKeyPressed(evt);
                    }
                });
            }
            {
                goto_but = new JButton();
                getContentPane().add(goto_but);
                goto_but.setText("\u8f6c \u5230");
                goto_but.setBounds(555, 36, 134, 44);
                goto_but.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        goto_butActionPerformed(evt);
                    }
                });
            }
            {
                jScrollPane1 = new JScrollPane();
                getContentPane().add(jScrollPane1);
                jScrollPane1.setBounds(12, 92, 676, 414);
                {
                    page_content = new JTextArea();
                    jScrollPane1.setViewportView(page_content);
                }
            }
            pack();
            this.setSize(708, 545);
        } catch (Exception e) {
            //add your error handling code here
            e.printStackTrace();
        }
    }
    
    private void goto_butActionPerformed(ActionEvent evt) {
        showPage();
    }
    
    private void url_textKeyPressed(KeyEvent evt) {
        if(evt.getKeyCode()==KeyEvent.VK_ENTER)
            showPage();
        
    }

    private void showPage() {
        try {
            
            String url_str = url_text.getText();
            URL url = new URL(url_str);
            
            InputStream in = url.openConnection().getInputStream();//url.openStream();
            
            page_content.setText("");
            
            byte[] buf = new byte[1024];
            int len = in.read(buf);
            String text = new String(buf,0,len,"utf-8");
            
            page_content.setText(text);
            
            in.close();
            
            
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

}
相關文章
相關標籤/搜索