第一节 | 第二节 | 第三节 | 第四节 | 第五节 | 第六节 | 第七节 | |||||
第六节 广播数据报
|
|||||||||||
广播数据报就是在网络通讯用广播方式传送给每个节点的数据包。 综合示例:网络聊天室 图10-13 ChatServer的运行结构 (1)聊天服务者ChatServer实现源程序如下: package char10; import java.net.*; import java.io.*; import java.util.*; public class ChatServer { /* m_threads是一个Vector静态变量,维护所有Server方的 ServerThread对象, * 通过该变量能向所有加入聊天室的聊天者ChatApplet广播信息,撤消退出的 * 聊天者。 * 聊天服务者ChatServer的主方法。该方法监听聊天者Chat Applet的请求, * 并为新连接的聊天者创建一个服务线程。 */ public static void main(String args[]) { ServerSocket socket=null; Vector m_threads=new Vector(); System.out.println("listen..."); try { //设置ServerServer监听端口号为5555, 这个数字必须 //和程序聊天者ChatApplet中的port参数一致。 socket=new ServerSocket(5555); } catch(Exception e) { System.out.println("new ServerSocket()failed!"); return; } try { int nid=0; while(true) { //监听是否有新聊天者Chat Applet连接到聊天Server, //线程运行到该语句会封锁,直到有新的连接产生。 Socket s=socket.accept(); System.out.println("accepted"); //创建一个新的ServerThread. ServerThread st=new ServerThread(s,m_threads); //为该线程设置一个ID号。 st.setID(nid++); //将该线程加入到m_threads Vector中。 m_threads.addElement(st); //启动服务线程。 new Thread(st). start(); //通知所有ChatApplet有一个新的网友加入。 for(int i=0;i { ServerThread st1=(ServerThread)m_threads.elementAt(i); st1.write("welcome "+st.getID()+" to enter chatroom!"); } System.out.println("Listen again..."); } } catch(Exception e) { System.out.println("Server is down..."); } } } /* * 监听线程,监听对应的Chat Applet是否有信息传来。 */ package cha10; import java.net.*; import java.io.*; import java.util.*; class ServerThread implements Runnable { Vector m_threads; Socket m_socket=null; DataInputStream m_in=null; DataOutputStream m_out=null; int m_nid; //初始化该线程。 public ServerThread(Socket s,Vector threads) { m_socket=s; m_threads=threads; try { //构造数据输入、输出流对象 m_in=new DataInputStream(m_socket.getInputStream()); m_out=new DataOutputStream(m_socket.getOutputStream()); } catch(Exception e) { } } public void run() //线程的执行体。 { System.out.println("thread is running"); try { while(true) { //监听对应的ChatApplet是否传来消息 //线程封锁在m_in.readUTF()中,直到有信息传来才返回。 String s=m_in.readUTF(); If (s==null) break; //如果Chat Applet传来的信息为"leave", //则通知所有其他的的ChatApplet自己退出了。 if (s.trim().equals ("leave")) for (int i=0;i { ServerThread st=(ServerThread)m_threads.elementAt(i); st.write("*** "+getID()+" leave..."+"***"); } else //向所有ChatApplet广播该信息。 for(int i=0;i { ServerThread st=(ServerThread)m_threads.elementAt(i); st.write(""+s); } } } catch(Exception e) { e.printStackTrace(); } //从m_threads Vector中删除该线程,表示该线程已经离开聊天室。 m_threads.removeElement(this); try { m_socket.close(); } catch (Exception e){} } //将msg送回对应的Applet public void write (String msg) { synchronized(m_out) { try { m_out.writeUTF(msg); } catch(IOException e){} } } public int getID() //获得该线程的ID. { return m_nid; } public void setID(int nid) // //设置线程的ID. { m_nid=nid; } } (2)聊天者ChatApplet源程序 聊天者源程序ChatApplet类提供三个主要方法: 1)Applet的初始化方法,负责启动监听线程 public void init(); 2)当聊天者在消息输入窗口键入回车后,读取字符串,发送给服务者方。 public boolean handleEvent(Event event); 3)监听对应的服务线程ServerThreadi,读取它传来的信息。 public void run(); 聊天者源程序ChatApplet1实现如下: package char10; import java.awt.*; import java.applet.*; import java.io.*; import java.net.*; //继承Applet,实现Runnable public class ChatApplet1 extends Applet implements Runnable{ TextArea m_textarea;//接受消息显示窗口 TextField m_textfield;//发送消息输入窗口 DataInputStream m_in; //消息输入流 DataOutputStream m_out; //消息输出流 /* *ChatApplet的初始化方法 */ public void init() { //创建窗口 setLayout(null); setSize(426,266); m_textarea=new TextArea(10,10); m_textfield=new TextField(); m_in=null; m_out=null; //初始化Applet,并连接到聊天服务者 try{ //获取applet 的URL ,即聊天服务者地址 URL url=getCodeBase(); //获取服务器IP地址 InetAddress inetaddr=InetAddress.getByName(url.getHost()); Socket m_socket; //屏幕显示服务器IP地址、通信协议 System.out.println("Server:"+inetaddr+" "+url.getHost()+" "+url.getProtocol()); //创建与服务器IP地址连接的套接口,5555是聊天服务者套接口端口 m_socket=new Socket(inetaddr,5555); //在套接口上建立输入流 m_in=new DataInputStream(m_socket.getInputStream()); //在套接口上建立输出流 m_out=new DataOutputStream(m_socket.getOutputStream()); } catch (Exception e) { System.out.println("Error:"+e); } setLayout(new BorderLayout()); add("Center",m_textarea); add("South",m_textfield); m_textarea.setEditable(false); //启动监听线程 new Thread(this).start(); } /*当聊天者在消息输入窗口键入回车后, *读取字符串,发送给聊天服务者。 */ public boolean handleEvent(Event event) { String b=m_textfield.getText(); if((event.target==m_textfield)&&(event.id==Event.ACTION_EVENT)) { m_textfield.setText(""); //将聊天者输入的消息发送给 ChatServer try{ m_out.writeUTF(b); //向聊天服务者发送一UTF格式字符串。 } catch(IOException e){} return true; } else return super.handleEvent(event); } /*聊天者监听对应的服务线程,在读取对应服务线程传来的消息, *并显示在通信显示窗口中。 */ public void run() { try { while(true) { //聊天者监听对应服务线程发来的消息,它将封锁在该语句中, //直到消息到来。 String s=m_in.readUTF(); //读一个UTF格式字符串。 if(s!=null) //将消息显示在信息显示窗口中。 m_textarea.append(s+"\n"); } } catch(Exception e) { m_textarea.append("Network problem or Server down.\n"); m_textfield.setVisible(false); } } public void stop() { try { m_out.writeUTF("leave"); } catch(IOException e){} } } 文字设置: 默认黑色 蓝色 绿色 默认大小 较大 较小 |
|||||||||||