Java网络编程技术1
1. Java网络编程常用API
1.1 InetAddress类使用示例
1.1.1根据域名查找IP地址
获取用户通过命令行方式指定的域名,然后通过InetAddress对象来获取该域名对应的IP地址。当然,程序运行时,需要计算机正常连接到Internet上。
例1. 根据域名查找IP地址
package Net; import java.net.InetAddress; import java.net.UnknownHostException; public class GetIP { public static void main(String[] args) { try { InetAddress ad = InetAddress.getByName(args[0]); //ad.getHostAddress()方法获取当前对象的IP地址 System.out.println("IP地址为:"+ad.getHostAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } } }
想获取网易的IP地址,就应该输入:java GetIP www.163.com
例2. 获取本机的IP地址。
package Net; import java.net.*; public class GetMyIP { public static void main(String[] args) { try { System.out.println(InetAddress.getLocalHost()); } catch (UnknownHostException e) { e.printStackTrace(); } } }
1.1.2 根据IP地址查找主机名
InetAddress亦可以根据给定的IP地址来查找对应的主机名。但要注意的是,它只能获取局域网内的主机名。
例3. 根据IP地址查找主机名。
package Net; import java.net.*; public class GetHostName { public static void main(String[] args) { try { InetAddress ad = InetAddress.getByName(args[0]); System.out.println("主机名为:"+ad.getHostName()); } catch (UnknownHostException e) { e.printStackTrace(); } } }
如果输入:java GetHostName www.sina.com
输出结果为: 主机名为:www.sina.com
如果输入的为局域网内的IP地址: java GetHostName 192.168.1.154
输出结果为: 主机名为:Tangliang
如果没有找到原样输出。
1.2 URL类和URLConnection类的使用
1.2.1 URL类的使用——一个简单的浏览器
这个程序的交互界面只有两个主要控件:JTextField和JEditPane。用户在JTextField中输入URL,完成后按回车键,程序将利用JEditPane来显示网页内容。
例4. 一个简单的浏览器示例。
package Net; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.*; public class myBrowser implements ActionListener,HyperlinkListener { JFrame jf; JLabel jl; JTextField jtf; JPanel jp; JEditorPane content; JScrollPane jsp; Container con; public myBrowser(){ jf = new JFrame("我的浏览器"); jl = new JLabel("请输入URL地址:"); jtf = new JTextField(); jtf.addActionListener(this); jtf.setColumns(20); jp = new JPanel(); jp.setLayout(new FlowLayout()); jp.add(jl); jp.add(jtf); content = new JEditorPane(); content.setEditable(false); content.addHyperlinkListener(this); jsp = new JScrollPane(content); con = jf.getContentPane(); con.add(jp, BorderLayout.NORTH); con.add(jsp, BorderLayout.CENTER); jf.setSize(800, 600); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void hyperlinkUpdate(HyperlinkEvent e) { if(e.getEventType()==HyperlinkEvent.EventType.ACTIVATED){ try { URL url = e.getURL(); //获取用户单击的URL content.setPage(url); //跳转到新页面 jtf.setText(url.toString()); //更新用户输入框中的URL } catch (IOException e1) { JOptionPane.showMessageDialog(jf, "找不到网页!"); } } } public void actionPerformed(ActionEvent e) { try { //根据用户输入构造URL对象 URL url = new URL(jtf.getText()); //获取网页内容并显示 content.setPage(url); } catch (MalformedURLException e1) { System.out.println(e1.toString()); } catch (IOException e1) { JOptionPane.showMessageDialog(jf, "找不到网页!"); } } public static void main(String[] args){ new myBrowser(); } }
上面的程序中,由于JEditorPane功能比较弱,无法执行网页中的JavaScript/VBScript等脚本语言,更无法执行ActiveX控件,所以只能用于一些静态网页的显示。
1.2.2 URLConnection类的使用——文件下载
文件下载的实质是从远程机器上复制文件到本地机器上,也就是说,它的本质不过是文件的复制。
例5. 文件下载示例。
package Net; import javax.swing.*; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.*; public class DownFile implements ActionListener { JFrame jf; Container con; JLabel jl; JTextField jtf; JButton btn; String name; public DownFile(){ jf = new JFrame("我的浏览器"); con = jf.getContentPane(); jl = new JLabel("请输入要下载文件的地址及名称:"); jtf = new JTextField(); jtf.setColumns(20); btn = new JButton("下载"); btn.addActionListener(this); con.setLayout(new FlowLayout()); con.add(jl); con.add(jtf); con.add(btn); jf.setSize(800, 600); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void actionPerformed(ActionEvent e) { try { name = JOptionPane.showInputDialog(jf, "请输入要保存的文件名"); URL url = new URL(jtf.getText()); //创建远程连接 URLConnection connect = url.openConnection(); //创建输入流 BufferedReader buf = new BufferedReader(new InputStreamReader(connect.getInputStream())); //创建输出流,保存文件名为temp.dat BufferedWriter file = new BufferedWriter(new FileWriter(name)); int ch; //复制文件 while((ch=buf.read())!=-1){ file.write(ch); } buf.close(); file.close(); JOptionPane.showMessageDialog(jf, "下载成功!"); } catch (MalformedURLException e1) { System.out.println(e1.toString()); } catch (IOException e1) { JOptionPane.showMessageDialog(jf, "连接出错!"); } } public static void main(String[] args) { new DownFile(); } }
2. Java Socket应用
2.1 示例程序1——端到端的通信
例6. 一个简单的客户/服务器的Socket通信程序。
package Net; import java.io.*; import java.net.*; public class Client { public static void main(String[] args) { try { //连接到本机,端口号为5500 Socket s = new Socket("localhost",5500); DataOutputStream dos = new DataOutputStream(s.getOutputStream()); DataInputStream dis = new DataInputStream(s.getInputStream()); System.out.println("请输入半径数值发送到服务器,输入bye表示结束。"); String outstr,instr; boolean goon = true; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while(goon){ outstr = br.readLine(); dos.writeUTF(outstr); dos.flush(); instr = dis.readUTF(); if(!instr.equals("bye")) System.out.println("从服务器返回的结果为:"+instr); else goon = false; } dis.close(); dos.close(); s.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
package Net; import java.io.*; import java.net.*; public class Server { public static void main(String[] args) { try { System.out.println("等待连接!"); ServerSocket ss = new ServerSocket(5500); Socket s = ss.accept(); System.out.println("连接者来自:"+s.getInetAddress().getHostAddress()); DataInputStream dis = new DataInputStream(s.getInputStream()); DataOutputStream dos = new DataOutputStream(s.getOutputStream()); boolean goon = true; double radius,area; String str; while(goon){ str = dis.readUTF(); if(!str.equals("bye")){ radius = Double.parseDouble(str); System.out.println("接收到的半径为:"+radius); area = radius*radius*Math.PI; dos.writeUTF(Double.toString(area)); dos.flush(); System.out.println("圆面积"+area+"已发送"); }else{ dos.writeUTF("bye"); dos.flush(); goon = false; } } dis.close(); dos.close(); ss.close(); } catch (IOException e) { e.printStackTrace(); } } }
程序运行结果如下:
客户端:
请输入半径数值发送到服务器,输入bye表示结束。 2 从服务器返回的结果为:12.566370614359172 3 从服务器返回的结果为:28.274333882308138 bye
服务器端:
等待连接! 连接者来自:127.0.0.1 接收到的半径为:2.0 圆面积12.566370614359172已发送 接收到的半径为:3.0 圆面积28.274333882308138已发送
2.2 示例程序2——一对多的通信
例7. 可以响应多个客户端的服务程序。
首先写一个服务器处理的线程类:
package Net; import java.io.*; import java.net.*; public class ServerThread extends Thread { private DataInputStream dis = null; private DataOutputStream dos = null; private Socket s = null; String str; public ServerThread(Socket s) throws IOException{ this.s = s; System.out.println("连接者来自:"+s.getInetAddress().getHostAddress()); dis = new DataInputStream(s.getInputStream()); dos = new DataOutputStream(s.getOutputStream()); start(); } public void run(){ try { boolean goon = true; double radius,area; String str; while(goon){ str = dis.readUTF(); if(!str.equals("bye")){ radius = Double.parseDouble(str); System.out.println("接收到的半径为:"+radius); area = radius*radius*Math.PI; dos.writeUTF(Double.toString(area)); dos.flush(); System.out.println("圆面积"+area+"已发送"); }else{ dos.writeUTF("bye"); dos.flush(); goon = false; } } dis.close(); dos.close(); s.close(); } catch (NumberFormatException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
写一个主程序使用线程:
package Net; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class MultiServer { public static void main(String[] args) { try { System.out.println("等待连接!"); ServerSocket ss = new ServerSocket(5500); Socket s = null; while(true){ s = ss.accept(); new ServerThread(s); } } catch (IOException e) { e.printStackTrace(); } } }
2.3 示例程序3——简单的聊天程序
例8. 聊天程序示例。
服务器端:
package Net.chat; import javax.swing.*; import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.*; public class chatServer implements ActionListener,Runnable{ JFrame jf; Container con; JPanel jp; JTextArea showArea; JTextField msgText; JButton btn; Thread thread; ServerSocket ss = null; Socket s = null; DataInputStream dis = null; DataOutputStream dos = null; public chatServer(){ jf = new JFrame("聊天————服务器"); con = jf.getContentPane(); jp = new JPanel(); jp.setLayout(new FlowLayout()); showArea = new JTextArea(); showArea.setEditable(false); msgText = new JTextField(); msgText.setColumns(20); btn = new JButton("发送"); btn.addActionListener(this); jp.add(msgText); jp.add(btn); con.add(showArea, BorderLayout.CENTER); con.add(jp, BorderLayout.SOUTH); jf.setSize(500, 400); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try { ss = new ServerSocket(8000); showArea.append("正在等待对话请求!\n"); s = ss.accept(); dis = new DataInputStream(s.getInputStream()); dos = new DataOutputStream(s.getOutputStream()); thread = new Thread(this); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } catch (IOException e) { showArea.append("对不起,没能创建服务器!\n"); msgText.setEditable(false); btn.setEnabled(false); } } public void run() { try { while(true){ showArea.append("对方说:"+dis.readUTF()+"\n"); Thread.sleep(1000); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public void actionPerformed(ActionEvent e) { String msg = msgText.getText(); try { if(msg.length()>0){ dos.writeUTF(msg); dos.flush(); showArea.append("我说:"+msg+"\n"); msgText.setText(null); } } catch (IOException e1) { showArea.append("你的消息"+msg+"未能发送出去!\n"); } } public static void main(String[] args) { new chatServer(); } }
客户端:
package Net.chat; import javax.swing.*; import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.*; public class chatClient implements ActionListener,Runnable{ JFrame jf; Container con; JPanel jp; JTextArea showArea; JTextField msgText; JButton btn; Thread thread; Socket s = null; DataInputStream dis = null; DataOutputStream dos = null; public chatClient(){ jf = new JFrame("聊天————客户端"); con = jf.getContentPane(); jp = new JPanel(); jp.setLayout(new FlowLayout()); showArea = new JTextArea(); showArea.setEditable(false); msgText = new JTextField(); msgText.setColumns(20); btn = new JButton("发送"); btn.addActionListener(this); jp.add(msgText); jp.add(btn); con.add(showArea, BorderLayout.CENTER); con.add(jp, BorderLayout.SOUTH); jf.setSize(500, 400); jf.setLocation(300, 200); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try { s = new Socket("localhost",8000); showArea.append("连接成功,请说话!\n"); dis = new DataInputStream(s.getInputStream()); dos = new DataOutputStream(s.getOutputStream()); thread = new Thread(this); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } catch (IOException e) { showArea.append("对不起,没能连接到服务器!\n"); msgText.setEditable(false); btn.setEnabled(false); } } public void run() { try { while(true){ showArea.append("对方说:"+dis.readUTF()+"\n"); Thread.sleep(1000); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public void actionPerformed(ActionEvent e) { String msg = msgText.getText(); try { if(msg.length()>0){ dos.writeUTF(msg); dos.flush(); showArea.append("我说:"+msg+"\n"); msgText.setText(null); } } catch (IOException e1) { showArea.append("你的消息"+msg+"未能发送出去!\n"); } } public static void main(String[] args) { new chatClient(); } }