程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> NameSender程序片

NameSender程序片

編輯:關於JAVA

正如早先指出的那樣,程序片必須用Java 1.0編寫,使其能與絕大多數的浏覽器適應。也正是由於這個原因,我們產生的類數量應盡可能地少。所以我們在這兒不考慮使用前面設計好的Dgram類,而將數據報的所有維護工作都轉到代碼行中進行。此外,程序片要用一個線程監視由服務器傳回的響應信息,而非實現Runnable接口,用集成到程序片的一個獨立線程來做這件事情。當然,這樣做對代碼的可讀性不利,但卻能產生一個單類(以及單個服務器請求)程序片:

 

//: NameSender.java
// An applet that sends an email address
// as a datagram, using Java 1.02.
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;

public class NameSender extends Applet 
    implements Runnable {
  private Thread pl = null;
  private Button send = new Button(
    "Add email address to mailing list");
  private TextField t = new TextField(
    "type your email address here", 40);
  private String str = new String();
  private Label 
    l = new Label(), l2 = new Label();
  private DatagramSocket s; 
  private InetAddress hostAddress;
  private byte[] buf = 
    new byte[NameCollector.BUFFER_SIZE];
  private DatagramPacket dp =
    new DatagramPacket(buf, buf.length);
  private int vcount = 0;
  public void init() {
    setLayout(new BorderLayout());
    Panel p = new Panel();
    p.setLayout(new GridLayout(2, 1));
    p.add(t);
    p.add(send);
    add("North", p);
    Panel labels = new Panel();
    labels.setLayout(new GridLayout(2, 1));
    labels.add(l);
    labels.add(l2);
    add("Center", labels);
    try {
      // Auto-assign port number:
      s = new DatagramSocket();
      hostAddress = InetAddress.getByName(
        getCodeBase().getHost());
    } catch(UnknownHostException e) {
      l.setText("Cannot find host");
    } catch(SocketException e) {
      l.setText("Can't open socket");
    } 
    l.setText("Ready to send your email address");
  }
  public boolean action (Event evt, Object arg) {
    if(evt.target.equals(send)) {
      if(pl != null) {
        // pl.stop(); Deprecated in Java 1.2
        Thread remove = pl;
        pl = null;
        remove.interrupt();
      }
      l2.setText("");
      // Check for errors in email name:
      str = t.getText().toLowerCase().trim();
      if(str.indexOf(' ') != -1) {
        l.setText("Spaces not allowed in name");
        return true;
      }
      if(str.indexOf(',') != -1) {
        l.setText("Commas not allowed in name");
        return true;
      }
      if(str.indexOf('@') == -1) {
        l.setText("Name must include '@'");
        l2.setText("");
        return true;
      }
      if(str.indexOf('@') == 0) {
        l.setText("Name must preceed '@'");
        l2.setText("");
        return true;
      }
      String end = 
        str.substring(str.indexOf('@'));
      if(end.indexOf('.') == -1) {
        l.setText("Portion after '@' must " +
          "have an extension, such as '.com'");
        l2.setText("");
        return true;
      }
      // Everything's OK, so send the name. Get a
      // fresh buffer, so it's zeroed. For some 
      // reason you must use a fixed size rather
      // than calculating the size dynamically:
      byte[] sbuf = 
        new byte[NameCollector.BUFFER_SIZE];
      str.getBytes(0, str.length(), sbuf, 0);
      DatagramPacket toSend =
        new DatagramPacket(
          sbuf, 100, hostAddress,
          NameCollector.COLLECTOR_PORT);
      try {
        s.send(toSend);
      } catch(Exception e) {
        l.setText("Couldn't send datagram");
        return true;
      }
      l.setText("Sent: " + str);
      send.setLabel("Re-send");
      pl = new Thread(this);
      pl.start();
      l2.setText(
        "Waiting for verification " + ++vcount);
    }
    else return super.action(evt, arg);
    return true;
  }
  // The thread portion of the applet watches for
  // the reply to come back from the server:
  public void run() {
    try {
      s.receive(dp);
    } catch(Exception e) {
      l2.setText("Couldn't receive datagram");
      return;
    }
    l2.setText(new String(dp.getData(),
      0, 0, dp.getLength()));
  }
} ///:~


程序片的UI(用戶界面)非常簡單。它包含了一個TestField(文本字段),以便我們鍵入一個電子函件地址;以及一個Button(按鈕),用於將地址發給服務器。兩個Label(標簽)用於向用戶報告狀態信息。
到現在為止,大家已能判斷出DatagramSocket、InetAddress、緩沖區以及DatagramPacket都屬於網絡連接中比較麻煩的部分。最後,大家可看到run()方法實現了線程部分,使程序片能夠“偵聽”由服務器傳回的響應信息。
init()方法用大家熟悉的布局工具設置GUI,然後創建DatagramSocket,它將同時用於數據報的收發。
action()方法只負責監視我們是否按下了“發送”(send)按鈕。記住,我們已被限制在Java 1.0上面,所以不能再用較靈活的內部類了。按鈕按下以後,采取的第一項行動便是檢查線程pl,看看它是否為null(空)。如果不為null,表明有一個活動線程正在運行。消息首次發出時,會啟動一個新線程,用它監視來自服務器的回應。所以假若有個線程正在運行,就意味著這並非用戶第一次發送消息。pl句柄被設為null,同時中止原來的監視者(這是最合理的一種做法,因為stop()已被Java 1.2“反對”,這在前一章已解釋過了)。
無論這是否按鈕被第一次按下,I2中的文字都會清除。
下一組語句將檢查E-mail名字是否合格。String.indexOf()方法的作用是搜索其中的非法字符。如果找到一個,就把情況報告給用戶。注意進行所有這些工作時,都不必涉及網絡通信,所以速度非常快,而且不會影響帶寬和服務器的性能。
名字校驗通過以後,它會打包到一個數據報裡,然後采用與前面那個數據報示例一樣的方式發到主機地址和端口編號。第一個標簽會發生變化,指出已成功發送出去。而且按鈕上的文字也會改變,變成“重發”(resend)。這時會啟動線程,第二個標簽則會告訴我們程序片正在等候來自服務器的回應。
線程的run()方法會利用NameSender中包含的DatagramSocket來接收數據(receive()),除非出現來自服務器的數據報包,否則receive()會暫時處於“堵塞”或者“暫停”狀態。結果得到的數據包會放進NameSender的DatagramPacketdp中。數據會從包中提取出來,並置入NameSender的第二個標簽。隨後,線程的執行將中斷,成為一個“死”線程。若某段時間裡沒有收到來自服務器的回應,用戶可能變得不耐煩,再次按下按鈕。這樣做會中斷當前線程(數據發出以後,會再建一個新的)。由於用一個線程來監視回應數據,所以用戶在監視期間仍然可以自由使用UI。

1. Web頁
當然,程序片必須放到一個Web頁裡。下面列出完整的Web頁源碼;稍微研究一下就可看出,我用它從自己開辦的郵寄列表(Mailling List)裡自動收集名字。
 

<HTML>
<HEAD>
<META CONTENT="text/html">
<TITLE>
Add Yourself to Bruce Eckel's Java Mailing List
</TITLE>
</HEAD>
<BODY LINK="#0000ff" VLINK="#800080" BGCOLOR="#ffffff">
<FONT SIZE=6><P>
Add Yourself to Bruce Eckel's Java Mailing List
</P></FONT>
The applet on this page will automatically add your email address to the mailing list, so you will receive update information about changes to the online version of "Thinking in Java," notification when the book is in print, information about upcoming Java seminars, and notification about the “Hands-on Java Seminar” Multimedia CD. Type in your email address and press the button to automatically add yourself to this mailing list. <HR>
<applet code=NameSender width=400 height=100>
</applet>
<HR>
If after several tries, you do not get verification it means that the Java application on the server is having problems. In this case, you can add yourself to the list by sending email to 
<A HREF="mailto:[email protected]">
[email protected]</A>
</BODY>
</HTML>

程序片標記(<applet>)的使用非常簡單,和第13章展示的那一個並沒有什麼區別。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved