網絡編程

這是我最頭疼的問題之一。。。問題本身不難,但是要提前考慮清楚一些細節。另外,我第一次面試就遇到一個問題:如果想把一個項目的數據導入到另一個項目中,我們該用什麼技術。我當時一臉懵逼,啥?數據該從數據庫拿就從數據庫拿,該從文件拿就從文件拿。。。結果面試老師說是網絡編程。。。我還能說什麼呢???說實話我從來沒想過用網絡編程來幹這個,我學的都是來來來,我給你發一條消息,你接收一下,完了給我個回覆之類的。

socket

又叫套接字,網絡編程中最基礎,最重要的概念,socket包含IP和端口號。socket通信:網絡上的兩個程序通過一個雙向通訊連接實現數據的交換,這個雙向鏈路的一端稱爲Socket

一) 網絡地址分類

1. A類地址分配給規模特別大的網絡使用。
    分配給具有大量主機(直接個人用戶)
    而局域網絡個數較少的大型網絡。例如IBM公司的網絡。

2. B 類地址 設計B類地址的目的是支持中到大型的網絡。 

3. C 類地址 C類地址用於支持大量的小型網絡。

注:
在編程前,需要測試你和對方的網絡是否通暢
通過ipconfig獲取自己的ip
通過ping ip測試你們是否能通信

二) TCP/IP五層網絡架構:

1.物理層:主要定義物理設備標準,
    如網線的接口類型、光纖的接口類型、
    各種傳輸介質的傳輸速率等。
    它的主要作用是傳輸比特流(就是由1、0轉化爲電流強弱來進行傳輸,
    到達目的地後在轉化爲1、0,也就是我們常說的數模轉換與模數轉換)。
    這一層的數據叫做比特。 
2. 數據鏈路層:
    主要將從物理層接收的數據進行MAC地址(網卡的地址)的封裝與解封裝。
    常把這一層的數據叫做幀。
    在這一層工作的設備是交換機,數據通過交換機來傳輸。 
3. 網絡層:
    主要將從下層接收到的數據進行IP地址(例192.168.0.1)的封裝與解封裝。
    在這一層工作的設備是路由器,常把這一層的數據叫做數據包。 
4. 傳輸層:定義了一些傳輸數據的協議和端口號(WWW端口80等),
    如:TCP(傳輸控制協議,傳輸效率低,可靠性強,用於傳輸可靠性要求高,數據量大的數據),
    UDP(用戶數據報協議,與TCP特性恰恰相反,用於傳輸可靠性要求不高,數據量小的數據。

7.應用層:直接爲用戶的應用進程提供服務,比如說FTP(各種文件下載),WEB(瀏覽器), QQ, 微信

注:關於tcp/ip的網絡架構這裏可能不全,有需要可以網上找相關資料

三 )通信三要素

兩臺計算機通信
ip: 確定主機地址
協議: 通信的規則
端口: 1~65535,  每一個端口標識一個進程

四) 重點

1) 基於tcp的通信
    a)客戶端發送信息,服務器接收
    b)客戶端發送信息,服務器回覆,客戶端在接收
    c)使用多線程,創建多客戶端連接的服務器

2) 基於udp的通信
    a) 發送端發送消息,接收端接受
    b) A端線發送,後接受,  B端先接受後發送

關於網絡編程,上面是最基本的5個案例,下面分別用代碼來實現

package socketProgramming;

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 Tcp1_ServerDemo {

    /**
     * tcp有三個例子,這是第一個
     * @throws IOException 
     * 
     */
    public static void main(String[] args) throws IOException {
        //1.創建服務端,監聽固定端口
        ServerSocket server=new ServerSocket(12345);
        //2.阻塞,等待客戶端連接
        while(true){
            Socket socket=server.accept();
            String ip=socket.getInetAddress().getHostName();
            System.out.println("客戶端連接成功");
            //3.獲取流對象
            InputStream is=socket.getInputStream();
            BufferedReader br=new BufferedReader(new InputStreamReader(is));
            //4.讀取數據
            String msg=br.readLine();
            System.out.println(ip+":"+msg);
            is.close();
            br.close();
            socket.close();
        }

    }

}

package socketProgramming;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Tcp1_ClientDemo {

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

        //1.創建客戶端
        Socket socket=new Socket("localhost",12345);
        System.out.println("連接服務器");
        //2.獲取流對象
        OutputStream os=socket.getOutputStream();
        byte[]byts="你好,我是客戶端".getBytes();
        os.write(byts);

        os.close();
        socket.close();
    }
}

==============第二個例子=============
package socketProgramming;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Tcp2_ServerDemo {

    /**
     * tcp有三個例子,這是第二個
     * @throws IOException 
     * 
     */
    public static void main(String[] args) throws IOException {
        //1.創建服務端,監聽固定端口
        ServerSocket server=new ServerSocket(10086);
        //2.等待客戶端連接

            Socket socket=server.accept();
            String ip=socket.getInetAddress().getHostName();
            System.out.println(ip+"客戶端連接成功");
            //3.獲取流對象
            InputStream is=socket.getInputStream();
            BufferedReader br=new BufferedReader(new InputStreamReader(is));
            OutputStream os=socket.getOutputStream();
            //4.讀取數據
            String msg=br.readLine();
            System.out.println(ip+":"+msg);
            //注意關閉輸入流,否則沒效果
            socket.shutdownInput();
            String msg_output="已經接收到數據";
            os.write(msg_output.getBytes());
            is.close();
            br.close();
            socket.close();


    }

}
package socketProgramming;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Tcp2_ClientDemo {

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

        //1.創建客戶端
        Socket socket=new Socket("localhost",10086);
        System.out.println("連接服務器");
        //2.獲取流對象
        OutputStream os=socket.getOutputStream();
        byte[]byts="你好,我是客戶端".getBytes();
        InputStream is=socket.getInputStream();
        BufferedReader br=new BufferedReader(new InputStreamReader(is));

        //3.
        os.write(byts);
        //注意關閉輸出流,否則沒效果
        socket.shutdownOutput();
        String msg=br.readLine();
        System.out.println("服務器回覆的數據:"+msg);



        is.close();
        br.close();

        os.close();
        socket.close();
    }
}

// 這個例子需要強調的就是不同方向的流的衝突問題,用完一個方向的流及時關閉

==============第三個例子====================
package socketProgramming;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Tcp3_ServerDemo {

    /**
     * tcp有三個例子,這是第三個,多客戶端連接
     * @throws IOException 
     * 
     */

    static ArrayList<Socket> alist=new ArrayList<>();
    public static void main(String[] args) throws IOException {
        //1.創建服務端,監聽固定端口
        ServerSocket server=new ServerSocket(10086);
        System.out.println("服務器啓動。。。");
        //2.等待客戶端連接
        while(true){
            Socket socket=server.accept();
            alist.add(socket);
            System.out.println("在線人數"+alist.size());

            //創建線程,與客戶端通信
            new Tcp3_SocketThread(socket).start();

        }

    }

}

package socketProgramming;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Tcp3_ClientDemo {

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

        //1.創建客戶端
        Socket socket=new Socket("localhost",10086);
        System.out.println("連接服務器");
        //2.獲取流對象
        OutputStream os=socket.getOutputStream();

        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        //3.發送數據
        String line=null;
        System.out.println("請輸入內容,輸出886退出");
        while((line=br.readLine())!=null){
            if("886".equals(line)){
                break;
            }
            //下面這句必須加,不加沒效果
            line=line+"\r\n";
            os.write(line.getBytes());
            os.flush(); 
            }

        br.close();

        os.close();
        socket.close();
    }
}
package socketProgramming;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class Tcp3_SocketThread extends Thread{

    private Socket socket;

    public Tcp3_SocketThread(Socket socket) {

        this.socket = socket;
    }

    @Override
    public void run() {

        String ip=socket.getInetAddress().getHostName();
        System.out.println(ip+"連接進來");
        //獲取流對象
        BufferedReader br=null;

        try {
            br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //讀取客戶端發來的數據
            String line=null;
            while((line=br.readLine())!=null){
                System.out.println(ip+":"+line);
            }
            br.close();


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}
=================第四個例子==================
package socketProgramming;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Udp1_Receive {

    /**
     * 基於UDP有兩個例子,這是第一個例子,也是我的第4個例子
     * @throws IOException 
     * 
     */

    public static void main(String[] args) throws IOException {
        //1.創建socket
        DatagramSocket receive=new DatagramSocket(12302);
        //2.接收數據
        byte[] buf=new byte[1024];
        DatagramPacket packet=new DatagramPacket(buf, 0, buf.length);
        receive.receive(packet);//阻塞,等待接收
        String ip=packet.getAddress().getHostAddress();
        System.out.println(ip+":"+new String(packet.getData()));

        //3.關閉資源
        receive.close();


    }

}
package socketProgramming;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class Udp1_Send {

    /**
     * 這是udp第一個例子的另一端
     * @throws IOException 
     */

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

        DatagramSocket socket=new DatagramSocket();
        String str="你好,客戶端";
        byte []data=str.getBytes();

        InetAddress address=InetAddress.getByName("127.0.0.1");
        DatagramPacket packet=new DatagramPacket(data,data.length,address,12302);

        socket.send(packet);

        socket.close();



    }
}


===============這是最後一個例子==============
package socketProgramming;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class Udp2_Receive {

    /**
     * 這是udp第二個例子,A端線發送,後接受,  B端先接受後發送
     * 需要注意的是,udp之間通信沒有固定的服務端和客戶端,通信雙方平等
     * 一端發送,另一端 就接收,反之亦然
     */
    public static void main(String[] args) {

        //1.創建socket對象
        DatagramSocket socket=null;

        try {
            socket=new DatagramSocket(11111);
            //2.獲取數據
            byte []buf=new byte[1024];
            DatagramPacket packet=new DatagramPacket(buf, buf.length);
            socket.receive(packet);//接收數據
            String ip=packet.getAddress().getHostAddress();
            System.out.println(ip+":"+new String(packet.getData()));

            //3.發送數據
            byte[]reply ="你好,我收到消息".getBytes();
            DatagramPacket replyPacket=new DatagramPacket(reply, reply.length,InetAddress.getByName("127.0.0.1"),10086);

            socket.send(replyPacket);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{

            if(socket!=null){
                socket.close();
            }
        }


    }




}


package socketProgramming;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class Udp2_Send {

    public static void main(String[] args) {

        //1.創建對象
        DatagramSocket socket=null;
        try {
            socket=new DatagramSocket(10086);
            //2.發送數據
            byte[]msg="你好,我是發送端,我線發送數據".getBytes();
            DatagramPacket packet=new DatagramPacket(msg, msg.length,InetAddress.getByName("127.0.0.1"),11111);
            socket.send(packet);

            //3.獲取數據
            byte []buf=new byte[1024];
            DatagramPacket receivePacket =new DatagramPacket(buf, buf.length);
            socket.receive(receivePacket);
            String ip=receivePacket.getAddress().getHostAddress();
            System.out.println(ip+":"+new String(receivePacket.getData()));




        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{

            if(socket!=null){
                socket.close();
            }
        }



    }

}

至此,網絡編程的五個簡單例子已經寫完,需要注意的一點是,運行程序時先運行接收端,再運行發送端,否則可能接收不到數據,上面五個例子是筆者挨個測試的可以運行,還有就是一些細節,比如幾個固定的類以及他們的方法,目前我的理解就這樣,以後有機會繼續添加

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章