天天看點

java與網絡(TCP)

1. 基本通信架構

資料封包長度不受限制。

  • Client端
System.out.println("-----Client-----");
//1、建立連接配接: 使用Socket建立用戶端 + 服務的位址和端口
Socket client =new Socket("localhost",8888); //目标位址及端口
//2、操作: 輸入輸出流操作
DataOutputStream dos =new DataOutputStream(client.getOutputStream());
String data ="hello"; //無需\r\n,自動加上
dos.writeUTF(data);
dos.flush();
//3、釋放資源 
dos.close();
client.close();      
  • Server端
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket建立伺服器
ServerSocket server =new ServerSocket(8888); //指定伺服器偵聽的端口
// 2、阻塞式等待連接配接 accept
Socket  client =server.accept(); //用戶端一連上就取消阻塞
System.out.println("一個用戶端建立了連接配接");
// 3、操作: 輸入輸出流操作
DataInputStream dis =new DataInputStream(client.getInputStream());
String data =dis.readUTF();
System.out.println(data);
// 4、釋放資源 
dis.close();
client.close();

server.close();      

2. 雙向通信

  • 用戶端
public class LoginTwoWayClient {

  public static void main(String[] args) throws UnknownHostException, IOException {
    System.out.println("-----Client-----");
    BufferedReader console =new BufferedReader(new InputStreamReader(System.in));
    System.out.print("請輸入使用者名:");
    String uname =console.readLine();
    System.out.print("請輸入密碼:");
    String upwd =console.readLine();
    
    //1、建立連接配接: 使用Socket建立用戶端 +服務的位址和端口
    Socket client =new Socket("localhost",8888);
    //2、操作: 輸入輸出流操作
    DataOutputStream dos =new DataOutputStream(client.getOutputStream());    
    dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
    dos.flush();
    
    DataInputStream dis =new DataInputStream(client.getInputStream());
    String result =dis.readUTF();    
    System.out.println(result);
    //3、釋放資源 
    dos.close();
    client.close();
  }
}      
  • 伺服器端
public class LoginTwoWayServer {

  public static void main(String[] args) throws IOException {
    System.out.println("-----Server-----");
    // 1、指定端口 使用ServerSocket建立伺服器
    ServerSocket server =new ServerSocket(8888);
    // 2、阻塞式等待連接配接 accept
    Socket  client =server.accept(); //用戶端一連上就取消阻塞
    System.out.println("一個用戶端建立了連接配接");
    // 3、操作: 輸入輸出流操作
    DataInputStream dis =new DataInputStream(client.getInputStream());
    String datas =dis.readUTF();
    String uname ="";
    String upwd ="";
    //分析
    String[] dataArray = datas.split("&");
    for(String info:dataArray) {
        String[] userInfo =info.split("=");
        if(userInfo[0].equals("uname")) {
          System.out.println("你的使用者名為:"+userInfo[1]);
          uname = userInfo[1];
        }else if(userInfo[0].equals("upwd")) {
          System.out.println("你的密碼為:"+userInfo[1]);
          upwd = userInfo[1];
        }        
    }
    //輸出
    DataOutputStream dos =new DataOutputStream(client.getOutputStream());      
    if(uname.equals("bee") && upwd.equals("123456")) { //成功
      dos.writeUTF("登入成功,歡迎回來");
    }else { //失敗
      dos.writeUTF("使用者名或密碼錯誤");
    }
    dos.flush();
    // 4、釋放資源 
    dis.close();
    client.close();
    
    server.close();
  }
}      

3. 檔案傳輸(對檔案大小沒有限制)

  • 用戶端上傳檔案
System.out.println("-----Client-----");
//1、建立連接配接: 使用Socket建立用戶端 +服務的位址和端口
Socket client =new Socket("localhost",8888); //目标位址及目标端口
//2、操作: 拷貝 上傳
InputStream is =new BufferedInputStream(new FileInputStream("src/foo.png"));
OutputStream os =new BufferedOutputStream(client.getOutputStream());
byte[] flush =new byte[1024];
int len = -1;
while((len=is.read(flush))!=-1) {
  os.write(flush,0,len);
}
os.flush();
//3、釋放資源 
os.close();
is.close();
client.close();      
  • 服務端接收檔案
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket建立伺服器
ServerSocket server =new ServerSocket(8888);
// 2、阻塞式等待連接配接 accept
Socket  client =server.accept(); //用戶端一連上就取消阻塞
System.out.println("一個用戶端建立了連接配接");
// 3、操作: 檔案拷貝 存儲
InputStream is =new BufferedInputStream(client.getInputStream());
OutputStream os =new BufferedOutputStream(new FileOutputStream("src/oof.png"));
byte[] flush =new byte[1024];
int len = -1;
while((len=is.read(flush))!=-1) {
  os.write(flush,0,len);
}
os.flush();
//3、釋放資源 
os.close();
is.close();

// 4、釋放資源 
client.close();

server.close();      

4. TCP多重連接配接

  • 伺服器端
public class LoginMultiServer {
  public static void main(String[] args) throws IOException {
    System.out.println("-----Server-----");
    // 1、指定端口 使用ServerSocket建立伺服器
    ServerSocket server =new ServerSocket(8888);
    boolean isRunning =true;
    // 2、阻塞式等待連接配接 accept
    while(isRunning) {
      Socket  client =server.accept();  //用戶端一連上就取消阻塞
      System.out.println("一個用戶端建立了連接配接");
      new Thread(new Channel(client)).start();
    }
    server.close();
  }
  //一個channel就代表一個用戶端
  static class Channel implements Runnable{
    private Socket  client;
    //輸入流
    private DataInputStream dis;
    //輸出流
    private DataOutputStream dos;
        
    public Channel(Socket  client) {
      this.client = client;
      try {
        //輸入
        dis = new DataInputStream(client.getInputStream());
        //輸出
        dos =new DataOutputStream(client.getOutputStream());  
      } catch (IOException e) {
        e.printStackTrace();
        release();
      }
      
    }
    
    //接收資料
    private String receive() {
      String datas ="";
      try {
        datas = dis.readUTF();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return datas;
    }
    //釋放資源
    private void release() {
      // 4、釋放資源 
      try {
        if(null != dos) {
          dos.close();          
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
      try {
        if(null != dis) {
          dis.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
      try {
        if(null != client) {
          client.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    //發送資料
    private void send(String msg) {
      try {
        dos.writeUTF(msg);
        dos.flush();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    @Override
    public void run() {            
      // 3、操作: 輸入輸出流操作          
      String uname ="";
      String upwd ="";
      //分析
      String[] dataArray = receive().split("&");
      for(String info:dataArray) {
          String[] userInfo =info.split("=");
          if(userInfo[0].equals("uname")) {
            System.out.println("你的使用者名為:"+userInfo[1]);
            uname = userInfo[1];
          }else if(userInfo[0].equals("upwd")) {
            System.out.println("你的密碼為:"+userInfo[1]);
            upwd = userInfo[1];
          }        
      }          
      if(uname.equals("bee") && upwd.equals("123456")) { //成功
        send("登入成功,歡迎回來");
      }else { //失敗
        send("使用者名或密碼錯誤");
      }
      release();
    }
  }
}      
  • 用戶端
public class LoginMultiClient {
  public static void main(String[] args) throws UnknownHostException, IOException {    
    System.out.println("-----Client-----");
    //1、建立連接配接: 使用Socket建立用戶端 +服務的位址和端口
    Socket client =new Socket("localhost",8888);
    //2、操作: 輸入輸出流操作  先請求後響應
    new Send(client).send();
    new Receive(client).receive();    
    client.close();
  }
  //發送
  static class Send{
    private Socket client;
    private DataOutputStream dos;
    private BufferedReader console ;
    private String msg;
    public Send(Socket client) {      
      console=new BufferedReader(new InputStreamReader(System.in));
      this.msg =init();
      this.client = client;
      try {
        dos=new DataOutputStream(client.getOutputStream());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    private String init() {          
      try {
        System.out.print("請輸入使用者名:");
        String uname =console.readLine();
        System.out.print("請輸入密碼:");
        String upwd =console.readLine();
        return "uname="+uname+"&"+"upwd="+upwd;
      } catch (IOException e) {
        e.printStackTrace();
      }
      return "";      
    }
    
    public void send() {
      try {
        dos.writeUTF(msg);
        dos.flush();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  //接收
  static class Receive{
    private Socket client;
    private DataInputStream dis;
    public Receive(Socket client) {
      this.client = client;
      try {
        dis=new DataInputStream(client.getInputStream());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }    
    public void receive() {
      String result;
      try {
        result = dis.readUTF();
        System.out.println(result);
      } catch (IOException e) {
        e.printStackTrace();
      }    
    }
  }
}