下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

如何用Java编写NameSender的程序片

作者:课课家教育     来源: http://www.kokojia.com点击数:539发布时间: 2016-02-29 19:46:27

标签: java编写java服务器java设计

大神带你学编程,欢迎选课

  正如早先指出的那样,程序片必须用java编写,使其能与绝大多数的浏览器适应。也正是由于这个原因,我们产生的类数量应尽可能地少。所以我们在这儿不考虑使用前面设计好的Dgram类,而将数据报的所有维护工作都转到代码行中进行。此外,程序片要用一个线程监视由服务器传回的响应信息,而非实现Runnable接口,用集成到程序片的一个独立线程来做这件事情。当然,这样做对代码的可读性不利,但却能产生一个单类(以及单个服务器请求)程序片:

如何用Java编写NameSender的程序片_java编写_java服务器_课课家

  //: 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)里自动收集名字。

  Add Yourself to Bruce Eckel's Java Mailing List

  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.

  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

  Bruce@EckelObjects.com

赞(12)
踩(2)
分享到:
华为认证网络工程师 HCIE直播课视频教程