Java基礎—網絡編程

一、網絡模型

OSI模型(七層):物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層。
TCP/IP模型(四層):物理層、網際層(IP)、傳輸層(TCP、UDP協議)、應用層(HTTP、FTP協議)。

二、網絡通訊三要素

1、IP地址:網絡中設備的唯一標識,java中描述IP的類是:InetAddreess。獲取本機的主機:InetAddress i = InetAddress.getLoclHost();獲取任一主機:InetAddress i = InetAddress.getByName(“192.168.2.56”);
2、端口:端口是用4爲數字表示的。常用的端口:SVN-3690,Tomacat-8080,Apache-80,mySQL-3306。
3、傳輸協議:常用的是TCP和UDP。

三、TCP、UDP

(一)、UDP
  1、UDP的特點:面向無連接,數據要封包,且不能大於64k,因爲無連接,所以不可靠,但是效率快。使用UDP協議傳輸的應用程序:QQ、桌面共享、網絡會議等。
  2、UDP傳輸:建立發送端、接收端,將數據打包,從發送端用send方法將數據包發送出去,接收端通過reveive方法將數據包接收到已定義好的數據包中,並用數據包的方法解析數據。關閉Socket服務。發送端和接收端是兩個獨立的運行程序。相關的類:DatagramSocketDatagramPacket
  3、建立UDP發送端服務的步驟:
    (1)、用DatagramSocket建立發送端Socket服務;
    (2)、確定要發送的數據,並用DatagramPacket將數據打包;
    (3)、用DatagramSocket裏的send方法將數據包發送出去;
    (4)、關閉Socket服務。
  4、建立UDP接收端服務的步驟:
    (1)、用DatagramSocket建立接收端的Socket服務;
    (2)、用DatagramPacket創建一個數據包;
    (3)、用DatagramSocket中的receive方法接收數據包,並將數據包存放在已定義好的數據包中。
    (4)、用DatagramPacket方法解析數據;
    (5)、關閉接收端Socket服務。
  5、模擬聊天功能

/*
聊天功能模擬。
分析:
     聊天,既能發送信息,也能接收信息,兩者同時進行,所以該用兩個線程來實現;

步驟:
    1、描述發送端,並實現Runnable接口;
    2、複寫run方法。
    3、用Thread建立線程;
    4、將Runnable的子類對象傳遞給Thread的構造函數;

其他說明:
         接收端沒接收端消息,先看看消息是否發送出去了。
*/
import java.net.*;
import java.io.*;
//建立發送端
class ChatSend implements Runnable
{
    private DatagramSocket ds;
    ChatSend(DatagramSocket ds)
    {
        this.ds = ds;
    }
    public void run()
    {
        BufferedReader bufr = null;
        DatagramPacket dp = null;
        try
        {
            //獲取鍵盤錄入對象
            bufr = new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            while((line = bufr.readLine()) != null)
            {
                //信息是以字節形式發送,所以需要將字符轉字節
                byte[] buf = line.getBytes();
                //將數據打包
                dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.75.1"),8887);
                //將數據包發送出去
                ds.send(dp);
                //判斷聊天結束標誌
                if(line.equals("goodbye"))
                {
                    //System.out.println(line+"聊天結束!");
                    break;
                }
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException("發送數據失敗!");
        }
        finally
        {
            if(bufr != null)
            {
                try
                {
                    bufr.close();
                }
                catch (IOException ie)
                {
                }
            }
        }
    }
}
//建立接收端
class ChatReceive implements Runnable
{
    private DatagramSocket ds;
    ChatReceive(DatagramSocket ds)
    {
        this.ds = ds;
    }
    public void run()
    {
        try
        {
            while(true)
            {
                //建立數據包,用於接收發送端發送過來的數據
                byte[] buf = new byte[1024];
                DatagramPacket dp = new DatagramPacket(buf,buf.length);
                ds.receive(dp);
                //用數據包方法解析數據
                String ip = dp.getAddress().getHostAddress();
                String data = new String(dp.getData(),0,dp.getLength());
                //判斷髮送端是否結束聊天
                if(data.equals("goodbye"))
                {
                    System.out.println("發送端結束聊天!");
                    break;
                }
                System.out.println(ip+"---"+data);
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException("數據接收失敗!");
        }
    }
}
class ChatTest
{
    public static void main(String[] args) 
    {
        try
        {
            //用Tread建立線程,開啓並執行進程
            new Thread(new ChatSend(new DatagramSocket())).start();
            new Thread(new ChatReceive(new DatagramSocket(8887))).start();
        }
        catch (IOException e)
        {
            throw new RuntimeException("建立聊天失敗!");
        }

    }
}

(二)、TCP
  1、TCP的特點:面向連接,兩者之間建立通訊通道,可在通道中進行大數據傳輸,安全可靠,但效率稍低。比如:下載。
  2、TCP傳輸:建立客戶端,並與服務器端建立連接,獲取客戶端的輸出流將數據發生到服務器端,服務器端通過獲取連接到該服務器上的客戶端的讀取流,獲取客戶端發送過來的信息,並用獲取到的客戶端的輸出流將客戶端需要的數據反饋給客戶端。涉及的類:客戶端:Socket,服務器端:ServerSocket。
  3、建立客戶端的步驟:
    (1)、通過Socket建立客戶端服務,並指定要連接的主機和端口;
    (2)、獲取輸出流;
    (3)、用輸出流將數據傳送到服務器;
    (4)、關閉Socket服務;
  4、建立服務器端的步驟:
    (1)、通過ServerSocket建立服務端服務;
    (2)、獲取連接到服務器的客戶端;
    (3)、通過獲取到的客戶端的讀取流,讀取客戶端發送過來的信息;
    (4)、關閉Socket服務(可選)。
  5、模擬併發圖片上傳

/*
客戶端併發上傳照片。
分析:客戶端併發上傳照片,要求服務端可以處理多個客戶端的請求。

主義事項:客戶端端將圖片信息發送結束,需要告訴服務端,數據已經發送結束,
           不然服務端在讀取數據時讀取不到結束標誌。
*/
import java.net.*;
import java.io.*;
class TcpPic
{
    public static void main(String[] args)
    {
        Socket s = null;
        FileInputStream ips = null;
        OutputStream out = null;
        InputStream in = null;
        try
        {
            //建立客戶端Socket服務,並指定要連接的主機
            s = new Socket("192.168.75.1",10000);
            //指定要上傳的圖片
            ips = new FileInputStream("ibeacon-01_05.png");
            //獲取網絡流中的輸出流,用於向服務端發送數據
            out = s.getOutputStream();
            byte[] buf = new byte[1024];
            int len = 0;
            //讀一次硬盤的圖片信息,想服務端發送一次
            while((len = ips.read(buf)) != -1)
            {
                out.write(buf,0,len);
            }
            //告訴服務端已經上傳完
            s.shutdownOutput();

            //獲取服務端返回的數據
            in = s.getInputStream();
            byte[] bt = new byte[1024];
            int lenth = in.read(bt);
            System.out.println(new String(bt,0,lenth));

            s.close();
        }
        catch (IOException e)
        {
            throw new RuntimeException("數據發送失敗!");
        }
        finally
        {
            if(ips != null)
            {
                try
                {
                    ips.close();
                }
                catch (IOException ie)
                {
                }
            }
        }
    }
}
//定義服務端
class ServerPic implements Runnable
{
    private Socket s;
    ServerPic(Socket s)
    {
        this.s = s;
    }
    public void run()
    {
        InputStream in = null;
        FileOutputStream ops = null;
        OutputStream out = null;
        try
        {
            //通過連接到服務端的客戶端對象獲取輸入流
            in = s.getInputStream();
            //獲取該客戶機的IP
            String path = s.getInetAddress().getHostAddress();
            int count = 0;
            File f = new File(path+"("+count+").png");
            //將文件名封裝成File對象,以便判斷文件名是否重複
            while(f.exists())
                f = new File(path+"("+(count++)+").png");
            //獲取將圖片信息寫到硬盤的輸出流
            ops = new FileOutputStream(f);
            //獲取將信息返回給客戶端的輸出流
            out = s.getOutputStream();
            byte[] buf = new byte[1024];
            int len = 0;
            //一邊讀取客戶端發送過來的數據,一邊將數據寫到硬盤中
            while((len = in.read(buf)) != -1)
            {
                ops.write(buf,0,len);
            }

            //給客戶端返回信息
            out.write("上傳成功!".getBytes());
            //System.out.println("商城成功");

            s.close();
        }
        catch (IOException e)
        {
            System.out.println(e.toString());
            throw new RuntimeException("圖片接收失敗!");
        }
        finally
        {
            if(ops != null)
            {
                try
                {
                    ops.close();
                }
                catch (IOException ie)
                {
                }
            }
        }
    }
}
class TcpPicTest
{
    public static void main(String[] args) 
    {
        ServerSocket ss = null;
        Socket s = null;
        try
        {
            //建立服務端Socket服務
            ss = new ServerSocket(10000);
            //獲取連接到該服務端的客戶端,並將其封裝到一個線程中。
            while(true)
            {
                s = ss.accept();
                //創建線程,開啓並執行線程代碼
                new Thread(new ServerPic(s)).start();
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException("服務端Socket建立失敗!");
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章