JAVA 網路

摘要:JAVA 網路

兩方通訊概念
  1. 先有對方ip
  2. 數據傳送到對方指定的應用程序上,以網路應用程序進行標誌,以數字代表,稱為埠
  3. 通信規則,即協議(TCP/IP)
 
IP地址
網路中設備的標誌,可用主機名,本地為127.0.0.1(localhotst)
 
埠:
標誌進程的邏輯地址,不用進程標誌,有效端口0~65536
 
UDP:
將數據及源和目的的封裝成數據包中,不需要建立連接,每個數據限制在64KB內,因無連接,所以為不可靠協議,不需要建立連接,速度快
 
TCP:
建立連接,形成傳輸數據的通道,在連接中進行大數據傳輸,通過三次握手完成連接,是可靠協議,必須建立連接,效率會稍低
 
查看本機:

import java.net.*;
class Hello{
    public static void main(String[] args)throws Exception{
        InetAddress i = InetAddress.getLocalHost();
        System.out.print(i);
    }
}

 

查看Google本機:


import java.net.InetAddress;
class Hello{
    public static void main(String[] args)throws Exception{
        InetAddress ia = InetAddress.getByName("www.google.com.tw");
        System.out.print(ia);
    }
}
Socket:
網路服務提供的一種機制,通信的兩端都有socket,數據在兩個socket間通過IO傳輸
 
DatagarmSocket
void receive(DatagramPacket p)
void send(DatagaramPacket p)

class UdpReceive{
    public static void main(String[] args)throws Exception{
       
        //創建udp socket建立端點
        DatagramSocket ds = new DatagramSocket(10000);
        while(true){//無窮迴圈等待接收
            //定義數據包用於存儲數據
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
       
            //通過服務的receive方法將收到的數據存入數據包中
            ds.receive(dp);
            String ip = dp.getAddress().getHostAddress();
            String output = new String (dp.getData(), 0 , dp.getLength());
            int port = dp.getPort();
       
            System.out.println(ip + "::" + output + "::" + port);
        }
        //關閉資源
        //ds.close();
    }
}

 


//需求: 通過udp傳輸方式,將一段文字數據發送出去
/**
* 1. 建立udpsocket服務
* 2. 提供數據, 並將數據封裝至數據包中
* 3. 通過socket服務的發送功能, 將數據包發出去*/

class Hello{
    public static void main(String[] args)throws Exception{
       
        //創建udp服務  通過DatagramSocket物件
        DatagramSocket ds = new DatagramSocket();
       
        //確定數據,並封裝成數據包
        byte[] data = "udp 123123".getBytes();
        DatagramPacket dp =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.254"), 10000);
       
        //通過socket服務 將已有的數據包發送出去  通過send方法
        ds.send(dp);
        //關閉資源
        ds.close();
    }
}

 


class Hello{
    public static void main(String[] args)throws Exception{
        DatagramSocket ds = new DatagramSocket();
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

        String line = null;
        while((line = bufr.readLine()) != null){
            if("88".equals(line))
                break;
            byte[] buf = line.getBytes();
            DatagramPacket dp =
                   new DatagramPacket(buf, buf.length, InetAddress.getByName("114.34.185.121"), 10001);
            ds.send(dp);
        }
        ds.close();
    }
}

 


class UdpReceive{
    public static void main(String[] args)throws Exception{
      
        DatagramSocket ds = new DatagramSocket(10001);
        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());
      
            System.out.println(ip + "::" + data);
        }
    }
}
//192.168.1.255廣播
 
聊天範例
使用多執行緒來操作發送數據與接收數據
一個執行緒發送、一個執行緒接收

class Hello{
    public static void main(String[] args)throws Exception{
        DatagramSocket sendSoket = new DatagramSocket();
        DatagramSocket receivedSoket = new DatagramSocket(10002);
        new Thread(new Send(sendSoket)).start();
        new Thread(new Receive(receivedSoket)).start();
    }
}

class Send implements Runnable{
    private DatagramSocket ds;
    Send(DatagramSocket ds){
        this.ds = ds;
    }
    public void run(){
        try{
            BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            while((line = bufr.readLine()) != null){
                if("88".equals(line))
                    break;
                byte[] buf = line.getBytes();
                DatagramPacket dp =
                        new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"), 10002);
                ds.send(dp);
            }
            ds.close();
        }catch(Exception e){
            throw new RuntimeException("發送失敗");
        }
    }
}

class Receive implements Runnable{
    private DatagramSocket ds;
    Receive(DatagramSocket ds){
        this.ds = ds;
    }
    public void run(){
        try{
            BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            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());
                System.out.println(ip + "::" + data);
            }
        }catch(Exception e){
            throw new RuntimeException("接收失敗");
        }
    }
}

 

TCP:
Socker與ServerSocket
  1. 建立客戶端與服務器端
  2. 建立連接後,通過Socket中的IO流進行數據傳書
  3. 關閉Socket

import java.io.OutputStream;
import java.net.Socket;
//客戶端:
//通過查閱socket物件,發現在該物件建立時,就可以去連接指定主機
//因為tcp是物件導向,所以在建立socket時,就要有服務端存在,並連接成功
//連接後,在該通道進行數據的傳輸
 
class TcpClient{
    public static void main(String[] args)throws Exception{
        Socket s = new Socket("114.34.185.121", 10006);
        //為了發送數據,應該獲取socket流中的輸出流
        OutputStream out = s.getOutputStream();
        out.write("客戶端發送".getBytes());
        s.close();
    }
}
 
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
//服務端:
//建立服務端的socket服務 ServeSocket();並監聽一個埠
//獲取連接過來的客戶端物件,通過ServerSocket的accept方法(阻塞式)
//客戶端如果發送數據,服務端要使用對應的客戶端物件,並獲取到該客戶端物件的讀取流來讀取//數據,關閉服務器(可選)
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "... connected ");
       
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf, 0, len));
        s.close();
        ss.close();
    }
}

 

客戶端給服務端發送數據,服務端收到後,給客戶端反饋訊息
  1. 建立Socket服務,指定要連接的主機與埠
  2. 獲取Socket流中的輸出流,將數據寫到該流中,通過網路發送給服務端
  3. 獲取Socket流中的輸入流,將服務端反饋的數據獲取到,並印出
  4. 關閉客戶端資源

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
 
class TcpClient {
    public static void main(String[] args)throws Exception{
        Socket s = new Socket("114.34.185.121", 10006);
   
        OutputStream out = s.getOutputStream();
        out.write("客戶端發送".getBytes());
       
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf, 0, len));
        s.close();
    }
}
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "... connected ");
       
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf, 0, len));
       
        OutputStream out = s.getOutputStream();
        out.write("收到訊息".getBytes());
        s.close();
        ss.close();
    }
}

 

需求: 建立一個文本轉換服務器
客戶端傳送資料給服務端,服務端會將文本轉為大寫後再傳送給客戶端
客戶端可以持續傳送,直接傳送over結束

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
 
//客戶端
//使用io操作方式  來源:由鍵盤輸入  目的:網路設備輸出流
//操作文本數據,可以選擇字元流
 
class TcpServer {
    public static void main(String[] args)throws Exception{
        Sockets = new Socket("114.34.185.121", 10006);
        //讀取鍵盤輸入
        BufferedReader bufr =
                new BufferedReader(new InputStreamReader(System.in));
        //將數據寫入到socket輸出流,發給服務端
        BufferedWriter bufOut =
                new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        BufferedReader bufIn =
                new BufferedReader(new InputStreamReader(s.getInputStream()));
       
        String line = null;
        while((line = bufr.readLine()) != null){
            if("over".equals(line))
                break;
            bufOut.write(line);
            bufOut.newLine();//發送enter給服務端
            bufOut.flush();//刷新
            String str = bufIn.readLine();
            System.out.println("Server:" + str);
 
        }
        bufr.close();
        s.close();
    }
}

 


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
//服務端
//來源: socket讀取流,目的:socket輸出流
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "... connected ");
        //讀取socket數據
        BufferedReader bufIn =
                new BufferedReader(new InputStreamReader(s.getInputStream()));
        //目的 socket輸出流 將大寫數據寫入到socket輸出流
        //並發送給輸出端
        BufferedWriter bufOut =
                new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while((line = bufIn.readLine()) != null){
            bufOut.write(line.toUpperCase());
            bufOut.newLine();
            bufOut.flush();
        }
        s.close();
        ss.close();
    }
}

 

服務端接收數據並儲存到檔案中


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
 
class Hello{
    public static void main(String[] args)throws Exception{
        Socket s = new Socket("114.34.185.121", 10006);
 
        BufferedReader bufr =
                new BufferedReader(new FileReader("C:\\Test.txt"));
       
        PrintWriter out = new PrintWriter(s.getOutputStream(), true);
       
        String line = null;
        while((line = bufr.readLine()) != null){
            out.println(line);
        }
        s.shutdownOutput();//關閉客戶端輸出流,相當於給流中加入一個結束標記 -1
       
        BufferedReader bufIn =
                new BufferedReader(new InputStreamReader(s.getInputStream()));
        String str = bufIn.readLine();
        System.out.println(str);
 
        bufr.close();
        s.close();
    }
}

 


import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        Socket s = ss.accept();
       
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "... connected ");
 
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
        PrintWriter out = new PrintWriter(new FileOutputStream("C:\\Server.txt"), true);
       
        String line = null;
        while((line = bufIn.readLine()) != null){
            if("over".equals(line))
                break;
            out.println(line);
        }
        PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
        pw.println("上傳成功");
 
        out.close();
        s.close();
        ss.close();
    }
}

 

上傳圖片


import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
 
class Hello{
    public static void main(String[] args)throws Exception{
        Socket s = new Socket("114.34.185.121", 10006);
        FileInputStream fis = new FileInputStream("1.bmp");
        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 num = in.read(bufIn);
        System.out.println(new String(bufIn, 0, num));
 
        fis.close();
        s.close();
    }
}
 
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        Socket s = ss.accept();
       
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "... connected ");
 
        InputStream in = s.getInputStream();
        FileOutputStream fos = new FileOutputStream("server.bmp");
 
        byte[] buf = new byte[1024];
        int len = 0;
        while((len = in.read(buf)) != -1){
            fos.write(buf, 0, len);
        }
        OutputStream out = s.getOutputStream();
        out.write("上傳成功".getBytes());
 
        fos.close();
        s.close();
        ss.close();
    }
}

 

服務端
當a連接上後,被服務端獲取到,服務端執行具體流程
若b也要連接,會成為等待狀態,因為服務端還沒有處理完a的請求
 
為了解決此問題,則服務端最好就是將每個客戶端封裝到一個單獨的執行緒中,這樣才能同時處理多的客戶端請求

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
 
 
class Hello{
    public static void main(String[] args)throws Exception{
        Socket s = new Socket("114.34.185.121", 10006);
        FileInputStream fis = new FileInputStream("1.bmp");
        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 num = in.read(bufIn);
        System.out.println(new String(bufIn, 0, num));
 
        fis.close();
        s.close();
    }
}
 
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;
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        while(true){
            Socket s = ss.accept();
            new Thread(new PicThread(s)).start();
        }
    }
}
 
class PicThread implements Runnable{
    private Socket s;
    public PicThread(Socket s) {
        this.s = s;
    }
    public void run(){
        int count = 1;
        String ip = s.getInetAddress().getHostAddress();
        try{
            System.out.println(ip + "... connected ");
            InputStream in = s.getInputStream();
           
            File file = new File(ip +"("+(count)+")" + ".jpg");
            while(file.exists())
                file = new File(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);
            }
            OutputStream out = s.getOutputStream();
 
            out.write("上傳成功".getBytes());
 
            fos.close();
            s.close();
        }catch(Exception e){
            throw new RuntimeException(ip + "上傳失敗");
        }
    }
}

 

登錄範例


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
 
class Hello{
    public static void main(String[] args)throws Exception{
        Socket s = new Socket("114.34.185.121", 10006);
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(s.getOutputStream(), true);
        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
       
        for(int x = 0; x < 3; x++){
            String line = bufr.readLine();
            if(line == null)
                break;
            out.println(line);
            String info = bufIn.readLine();
            System.out.println("info:" + info);        
            if(info.contains("Welcome"))
                break;
        }
        bufr.close();
        s.close();
    }
}
 
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        while(true){
            Socket s = ss.accept();
            new Thread(new UserThread(s)).start();
        }
    }
}
 
class UserThread implements Runnable{
    private Socket s;
    public UserThread(Socket s) {
        this.s = s;
    }
    public void run(){
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip + "...connected");
        try{
            for(int x = 0; x < 3; x++){
                BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
                String name = bufIn.readLine();
                BufferedReader bufr = new BufferedReader(new FileReader("G:\\user.txt"));
                PrintWriter out = new PrintWriter(s.getOutputStream(), true);
                String line = null;
               
                boolean flag = false;
                while((line = bufr.readLine())!= null){
                    if(line.equals(name)){
                        flag = true;
                        break;
                    }
                }
                if(flag){
                    System.out.println(name + "登入");
                    out.println(name + "  Welcome!");
                    break;
                }else{
                    System.out.println(name + "嘗試登入");
                    out.println(name + "用戶不存在");
                   
                }
            }
            s.close();
        }catch(Exception e){
            throw new RuntimeException(ip + "校驗失敗");
        }
    }
}

 

客戶端與服務端
客戶端:瀏覽器
服務端:自定義

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
class TcpServer{
    public static void main(String[] args) throws IOException{
        ServerSocket ss = new ServerSocket(10006);
        //  http://192.168.0.1:10006/
        Socket s = ss.accept();
        System.out.println(s.getInetAddress().getHostAddress());
 
        PrintWriter out = new PrintWriter(s.getOutputStream(), true);
        out.println("客戶端你好");
        s.close();
        ss.close();
    }
}