雙工連線應用

半雙工(half-duplex)的服務能進行雙向資料傳輸,但不能同時進行。因此同一時間只允許一裝置傳送資料,若另一裝置要傳送資料,需等原來傳送資料的裝置傳送完成後再處理。全雙工(full-duplex)的系統允許二台裝置間同時進行雙向資料傳輸。在傳送資料時同時也可以接收資料,並且進行相應的工作。

半雙工

半雙工的系統可以比喻作單線雙向道路,若道路上無車時任一方向的車都可以通過。但若道路上有車,相反方向的車需等待路途中的車通過道路後才能通過。無線電對講機就是使用半雙工系統。由於對講機傳送及接收使用相同的頻率,不允許同時進行。因此一方講完後,需設法告知另一方講話結束,另一方才知道可以開始講話。

半雙工客戶端(Client)程式 Socket05

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;

public class Socket05 {
 /**
  * 觸發半雙工伺服器
  * 
  * @param args
  * @throws IOException
  */
 public static void main(String args[]) throws IOException {

  BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
  System.out.print("請輸入IP: ");
  String ip = buf.readLine();// 讀取輸入值為IP

  System.out.print("請輸入連接埠: ");
  int port = Integer.parseInt(buf.readLine()); // 讀取輸入值為port
  Socket socket = new Socket(InetAddress.getByName(ip), port);// 建立Socket連線

  DataOutputStream out = new DataOutputStream(socket.getOutputStream());
  DataInputStream input = new DataInputStream(socket.getInputStream());
  
  String msg;
  while(true) {   
   System.out.print("請輸入訊息: "); 
   msg=buf.readLine();
   out.writeUTF(msg);
   if(msg.equals("bye"))break;  
   
   msg = input.readUTF();
   System.out.println("接收到訊息: " + msg);     
   if(msg.equals("bye"))break;   
  }
  input.close();
  out.close();
  socket.close();// 結束連線
  System.out.println("與 "+ip+" 連線已結束");
 }
}


建立半雙工的通信需要具備輸入串流與輸出串流
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
在迴圈中依照輸入或輸出的串流做readUTF、writeUTF方法將字串編成UTF-8格式存取。
outstream.writeUTF(msg);
...
...
msg = input.readUTF();


半雙工主機端(Server)程式 Socket06

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Socket06 {
 /**
  * 半雙工伺服器
  * @param args
  * @throws IOException
  * @throws InterruptedException
  */
 public static void main(String args[]) throws IOException {
  Socket socket;
  BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
  DataInputStream input;
  DataOutputStream out;
  System.out.print("請輸入連接埠號: ");
  String port = buf.readLine();
  ServerSocket server = new ServerSocket(Integer.parseInt(port));
  System.out.print("本機位址: " + InetAddress.getLocalHost().getHostAddress());
  System.out.println(" 開放連接埠: " + port);
  System.out.println("伺服器已建立, 等待連接...");  
  String msg, ip;
  while (true) {
   socket = server.accept();
   ip=socket.getInetAddress().getHostAddress();
   System.out.println("現在與 " + ip + "連線");
   System.out.println("對方的電腦名稱:" + socket.getInetAddress().getHostName());
   java.awt.Toolkit.getDefaultToolkit().beep();
   input = new DataInputStream(socket.getInputStream());
   out = new DataOutputStream(socket.getOutputStream());
   while(true) {
    msg = input.readUTF();
    System.out.println("接收到訊息: " + msg);     
    if(msg.equals("bye"))break;
    
    System.out.print("請輸入訊息: ");
    msg=buf.readLine();
    out.writeUTF(msg);
   }
   System.out.println("與 "+ip+" 連線已結束");
   input.close(); 
   out.close();
   socket.close();
   //server.close();
  }  
 }
}


建立半雙工的通信需要具備輸入串流與輸出串流
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
在迴圈中依照輸入或輸出的串流做readUTF、writeUTF方法將字串編成UTF-8格式存取。與客戶端的連線結束後,並不會結束伺服器的服務。
while(true){
  ...
  ...
  while(true){


  }

}


建立桌面應用程式

網路連線運作,經過設計後可以進一步應用在個人電腦成為通訊軟體。建立個人電腦上的應用程式,大多使用視窗操作介面。使用JAVA建立視窗介面可以參考這裡

桌面應用的客戶端程式至少需要下列元件,包括終端機介面中的所有輸入/出參數,以及取代暫存鍵盤輸入及終端機輸出。

請依據範例建立視窗,並且設定相對應的名稱。
可以使用範例中的建議名稱,或是自定易記名稱。
請注意,終端機視窗、訊息輸入欄位以及發送按鈕預設都是關閉使用的。
請至少要關閉掉發送按鈕

客戶端(Client)視窗程式(片段) Socket07 


需要具備的工具先設定為全域可以存取的物件,因此放在最外層的範圍。

Socket socket;
DataOutputStream out;
DataInputStream input;


 
Socket socket;
DataOutputStream out;
DataInputStream input;

客戶端(Client)連線按鈕

在設計模式下(Design)以滑鼠連點2下連線用的按鈕物件,就會自動切到原始碼模式(Source)按鈕觸發的程式區塊。將下列程式碼複製進去,讓連線按鈕發生作用。
try {
     socket = new Socket(InetAddress.getByName(ip.getText()), Integer.parseInt(port.getText()));// 建立Socket連線
     out = new DataOutputStream(socket.getOutputStream());
     input = new DataInputStream(socket.getInputStream());
     
     info.setEnabled(true);
     msg.setEnabled(true);
    }catch(Exception ex) {
     
    }

客戶端(Client)訊息發送按鈕

在設計模式下(Design)以滑鼠連點2下連線用的按鈕物件,就會自動切到原始碼模式(Source)按鈕觸發的程式區塊。將下列程式碼複製進去,讓連線按鈕發生作用。




    info.append("我: "+msg.getText()+"\n");    
    System.out.println(msg.getText());
    try {
     out.writeUTF(msg.getText());     
     while(true) {
      info.append("對方: "+input.readUTF()+"\n");
      break;  
     } 
    } catch (IOException ex) {     
     ex.printStackTrace();
    }






IOException的威力強大,絕對不輸給其他角色。

提示1: 用到.io的物件方法就是要有close()
提示2: 用到.io的物件方法就是要有try - catch

沒有留言:

張貼留言