实验1 读取服务器端的文件
一、实验目的
学会使用URL对象
二、实验内容
创建一个URL对象,然后让URL对象返回输入流,通过该输入流读取URL所包含的资源文件。
三、程序代码
1. import java.awt.*; 2. import java.awt.event.*; 3. import java.net.*; 4. import java.io.*; 5. import javax.swing.*; 6. public class ReadURLSource { 7. public static void main(String args[]) { 8. new NetWin(); 9. } 10. } 11. class NetWin extends JFrame implements ActionListener,Runnable { 12. JButton button; 13. URL url; 14. JTextField inputURLText; //输入URL 15. JTextArea area; 16. byte b[]=new byte[118]; 17. Thread thread; 18. NetWin() { 19. inputURLText=new JTextField(20); 20. area=new JTextArea(12,12); 21. button=new JButton("确定"); 22. button.addActionListener(this); 23. thread=new Thread(this); 24. JPanel p=new JPanel(); 25. p.add(new JLabel("输入网址:")); 26. p.add(inputURLText); 27. p.add(button); 28. add(area,BorderLayout.CENTER); 29. add(p,BorderLayout.NORTH); 30. setBounds(60,60,560,300); 31. setVisible(true); 32. validate(); 33. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 34. } 35. public void actionPerformed(ActionEvent e) { 36. if(!(thread.isAlive())) 37. thread=new Thread(this); 38. try{ thread.start(); 39. } 40. catch(Exception ee) { 41. inputURLText.setText("我正在读取"+url); 42. } 43. } 44. public void run() { 45. try { int n=-1; 46. area.setText(null); 47. String name=inputURLText.getText().trim(); 48. url = new URL(name);//使用字符串name创建url对象 49. String hostName = url.getHost();url调用getHost() 50. int urlPortNumber = url.getPort(); 51. String fileName=url.getFile(); 52. InputStream in = url.openStream();//url调用方法返回一个输入流 53. area.append("\n主机:"+hostName+"端口:"+urlPortNumber+ 54. "包含的文件名字:"+fileName); 55. area.append("\n文件的内容如下:"); 56. while((n=in.read(b))!=-1) { 57. String s=new String(b,0,n); 58. area.append(s); 59. } 60. } 61. catch(MalformedURLException e1) { 62. inputURLText.setText(""+e1); 63. return; 64. } 65. catch(IOException e1) { 66. inputURLText.setText(""+e1); 67. return; 68. } 69. } 70. }
四、实验指导
1、java.net包中的URL类是对统一资源定位符的抽象,使用URL创建对象的应用程序称作客户端程序,一个URL对象存放着一个具体的资源的引用,表明客户要访问这个URL中的资源,利用URL对象可以获取URL中的资源。
2、URL对象调用InputStream openStream()方法可以返回一个输入流,该输入流指向URL对象所包含的资源。通过该输入流可以将服务器上的资源信息读入到客户端。
3、URL资源的读取可能会引起阻塞,因此,程序需要在一个线程中读取URL资源,以免堵塞主线程。
实验2 会结帐的服务器
一、实验目的
学会使用套接字读取服务器端的对象
二、实验内容
客户端和服务器建立套接字连接后,客户将如下的账单发送给服务器:
房租:2189元 水费:112.9元 电费:569元 物业费:832元
服务器返回客户端的信息是:
您的账单
房租:2189元 水费:112.9元 电费:569元 物业费:832元
总计:3699.9元
三、程序代码
客户端:ClientItem.java
1. import java.io.*; 2. import java.net.*; 3. import java.util.*; 4. public class ClientItem { 5. public static void main(String args[]) { 6. Scanner scanner = new Scanner(System.in); 7. Socket clientSocket=null; 8. DataInputStream inData=null; 9. DataOutputStream outData=null; 10. Thread thread ; 11. Read read=null; 12. try{ clientSocket=new Socket(); 13. read = new Read(); 14. thread = new Thread(read); //负责读取信息的线程 15. System.out.print("输入服务器的IP:"); 16. String IP = scanner.nextLine(); 17. System.out.print("输入端口号:"); 18. int port = scanner.nextInt(); 19. String enter=scanner.nextLine(); //消耗回车 20. if(clientSocket.isConnected()){} 21. else{ 22. InetAddress address=InetAddress.getByName(IP); 23. InetSocketAddress socketAddress=new InetSocketAddress(address,port); 24. clientSocket.connect(socketAddress); 25. InputStream in= clientSocket.getInputStream();//clientSocket调用getInputStream()返回该套接字的输入流 26. OutputStream out= clientSocket.getOutputStream();//clientSocket调用getOutputStream()返回该套接字的输出流 27. inData =new DataInputStream(in); 28. outData = new DataOutputStream(out); 29. read.setDataInputStream(inData); 30. read.setDataOutputStream(outData); 31. thread.start(); //启动负责读信息的线程 32. } 33. } 34. catch(Exception e) { 35. System.out.println("服务器已断开"+e); 36. } 37. } 38. } 39. class Read implements Runnable { 40. Scanner scanner = new Scanner(System.in); 41. DataInputStream in; 42. DataOutputStream out; 43. public void setDataInputStream(DataInputStream in) { 44. this.in = in; 45. } 46. public void setDataOutputStream(DataOutputStream out) { 47. this.out = out; 48. } 49. public void run() { 50. System.out.println("输入账单:"); 51. String content = scanner.nextLine(); 52. try{ out.writeUTF("账单"+content); 53. String str = in.readUTF(); 54. System.out.println(str); 55. str = in.readUTF(); 56. System.out.println(str); 57. str = in.readUTF(); 58. System.out.println(str); 59. } 60. catch(Exception e) {} 61. } 62. }
服务器端:ServerItem.java
1. import java.io.*; 2. import java.net.*; 3. import java.util.*; 4. public class ServerItem { 5. public static void main(String args[]) { 6. ServerSocket server=null; 7. ServerThread thread; 8. Socket you=null; 9. while(true) { 10. try{ server= new ServerSocket(4331);//创建在端口4331上负责监听的 ServerSocket对象 11. } 12. catch(IOException e1) { 13. System.out.println("正在监听"); 14. } 15. try{ System.out.println("正在等待客户"); 16. you= server.accept();//server调用accept()返回和客户端相连接的Socket对象 17. System.out.println("客户的地址:"+you.getInetAddress()); 18. } 19. catch (IOException e) { 20. System.out.println(""+e); 21. } 22. if(you!=null) { 23. new ServerThread(you).start(); 24. } 25. } 26. } 27. } 28. class ServerThread extends Thread { 29. Socket socket; 30. DataInputStream in=null; 31. DataOutputStream out=null; 32. ServerThread(Socket t) { 33. socket=t; 34. try { out=new DataOutputStream(socket.getOutputStream()); 35. in=new DataInputStream(socket.getInputStream()); 36. } 37. catch (IOException e) {} 38. } 39. public void run() { 40. try{ 41. String item = in.readUTF(); 42. Scanner scanner = new Scanner(item); 43. scanner.useDelimiter("[^0123456789.]+"); 44. if(item.startsWith("账单")) { 45. double sum=0; 46. while(scanner.hasNext()){ 47. try{ double price = scanner.nextDouble(); 48. sum = sum+price; 49. System.out.println(price); 50. } 51. catch(InputMismatchException exp){ 52. String t = scanner.next(); 53. } 54. } 55. out.writeUTF("您的账单:"); 56. out.writeUTF(item); 57. out.writeUTF("总额:"+sum+"元"); 58. } 59. } 60. catch(Exception exp){} 61. } 62. }
四、实验指导
1、套接字连接中涉及输入输出流操作,可能会引起堵塞,我们把读取数据放在一个单独的线程中去进行。另外服务器收到客户套接字后,就应该启动一个专门为该客户服务的线程。
2、Socket对象调用public void connect(SocketAddress endpoint)方法可以和参数endpoint指定的SocketAddress地址建立套接字连接。
实验3 TCP网络通信
一、实验目的
掌握TCP网络通信的相关类的使用
二、实验内容
1、编写服务器端程序:
(1)创建一个服务器套接字(ServerSocket),绑定到指定端口;
(2)调用accept方法,侦听来自客户端的请求,如果客户发出请求,则接受连接,返回通信套接字(Socket);
(3)创建线程来处理客户机:
- 在线程中调用getOutputStream方法,获得输入/输出流;
- 每连上一个客户端,就主动给客户端发送一句“欢迎光临!”
- 使用Arraylist存放连上服务端的所有客户端
- 当接收到客户端发送来的消息的时候,将这条消息转发给是有连上服务端的所有客户端
- 关闭通信套接字,
(4)关闭服务器套接字。
2、编写客户端程序:
(1)创建一个套接字(Socket),向服务器的侦听端口发出请求;
(2)与服务器正确连接后,调用Socket的getlnputStream和getOutputStream方法,获得输入/输出流,启动线程开始网络数据的接收和发送;在命令行给服务端发送消息;当接收到服务端发来的消息的时候,将内容显示在控制台上
(3)关闭通信套接字
三、程序代码
客户端:TCPClient.java
1. import java.awt.BorderLayout; 2. import java.awt.Frame; 3. import java.awt.List; 4. import java.awt.TextField; 5. import java.awt.event.ActionEvent; 6. import java.awt.event.ActionListener; 7. import java.awt.event.WindowAdapter; 8. import java.awt.event.WindowEvent; 9. import java.io.DataInputStream; 10. import java.io.DataOutputStream; 11. import java.io.IOException; 12. import java.net.Socket; 13. import java.net.UnknownHostException; 14. 15. import javax.swing.JFrame; 16. 17. public class TCPClient extends JFrame { 18. Socket s = null; 19. DataOutputStream dos = null; 20. DataInputStream dis = null; 21. TextField tf = new TextField(40); 22. List list = new List(10); 23. public static void main(String[] args) { 24. TCPClient client = new TCPClient(); 25. client.list.add("向服务器端发送的数据:"); 26. client.setTitle("客户端"); 27. client.run(); 28. } 29. public void run() { 30. setLocation(400, 300); // 设置窗体的位置 31. this.setSize(300, 300); // 设置窗体的大小 32. add(tf, BorderLayout.SOUTH); 33. add(list, BorderLayout.NORTH); 34. pack(); //调整此窗口的大小,以适合其子组件的首选大小和布局。 35. this.addWindowListener(new WindowAdapter() { // 关闭窗体 36. public void windowClosing(WindowEvent e) { 37. disconnect(); 38. System.exit(0); 39. } 40. }); 41. tf.addActionListener(new MyListener()); // 注册事件监听器 42. setVisible(true); 43. connect(); 44. } 45. public void connect() { 46. try {//139.155.5.93 47. s = new Socket("127.0.0.1", 8866); // 创建一个向服务器发起连接的Socket对象 48. dos = new DataOutputStream(s.getOutputStream()); 49. } catch (UnknownHostException e) { 50. e.printStackTrace(); 51. } catch (IOException e) { 52. e.printStackTrace(); 53. } 54. } 55. public void disconnect() { 56. try { 57. dos.close(); // 关闭输出流 58. s.close(); // 关闭Socket对象 59. } catch (IOException e) { 60. e.printStackTrace(); 61. } 62. } 63. private class MyListener implements ActionListener { 64. public void actionPerformed(ActionEvent e) { 65. String s1 = null; 66. String s2 = null; 67. String str = tf.getText().trim(); // 获取文本框中的内容 68. list.add(str); 69. tf.setText(""); // 将文本框的内容清空 70. try { 71. dos.writeUTF(str); // 向流中写入数据 72. dos.flush(); // 刷空流 73. } catch (IOException e1) { 74. e1.printStackTrace(); 75. } 76. } 77. } 78. }
服务器端:TCPServer.java
1. import java.awt.BorderLayout; 2. import java.awt.Frame; 3. import java.awt.TextArea; 4. import java.awt.event.WindowAdapter; 5. import java.awt.event.WindowEvent; 6. import java.io.DataInputStream; 7. import java.io.EOFException; 8. import java.io.IOException; 9. import java.net.BindException; 10. import java.net.ServerSocket; 11. import java.net.Socket; 12. 13. import javax.swing.JFrame; 14. 15. public class TCPServer { 16. static DataInputStream dis = null; 17. public static void main(String[] args) { 18. boolean started = false; 19. Socket s = null; 20. TextArea ta = new TextArea(); 21. ta.append("从客户端接收的数据:"+"\n"); 22. ServerSocket ss = null; 23. try { 24. ss = new ServerSocket(8866); // 创建一个监听Socket对象 25. } catch (BindException e) { 26. System.exit(0); 27. } catch (IOException e) { 28. e.printStackTrace(); 29. } 30. JFrame f = new JFrame("服务器端"); 31. f.setLocation(300, 300); 32. f.setSize(200, 200); 33. f.add(ta, BorderLayout.NORTH); 34. f.pack(); 35. f.addWindowListener(new WindowAdapter() { // 关闭窗口 36. public void windowClosing(WindowEvent e) { 37. System.exit(0); 38. } 39. }); 40. f.setVisible(true); // 设置窗体可见 41. try { 42. started = true; 43. while (started) { 44. boolean bConnected = false; 45. s = ss.accept(); // 等待客户端请求连接 46. bConnected = true; 47. dis = new DataInputStream(s.getInputStream()); 48. while (bConnected) { 49. String str =s.getRemoteSocketAddress()+":"+ dis.readUTF(); // 从输入流中读取数据 50. ta.append(str+"\n"); // 将数据添加到文本区中 51. } 52. } 53. } catch (EOFException e) { 54. System.out.println("Client closed!"); 55. } catch (IOException e) { 56. e.printStackTrace(); 57. } finally { 58. try { 59. if (dis != null) 60. dis.close(); // 关闭输入流 61. if (s != null) 62. s.close(); // 关闭Socket对象 63. } catch (Exception e) { 64. e.printStackTrace(); 65. } 66. } 67. } 68. }
实验4 UDP网络通信
一、实验目的
掌握UDP网络通信的相关类的使用
二、程序代码
发送端:
1. import java.io.IOException; 2. import java.net.DatagramPacket; 3. import java.net.DatagramSocket; 4. import java.net.InetAddress; 5. import java.util.Scanner; 6. 7. public class SX10C {//主类 8. public static void main(String[] args) {//主方法 9. Scanner input=new Scanner(System.in); 10. System.out.print("这里是发送端,请输入要发送的数据:"); 11. String info1 = input.nextLine(); 12. input.close(); 13. try { 14. //创建发送端 Socket,使用4567端口 15. DatagramSocket socket = new DatagramSocket(4567); 16. String info2 = "接收端你好,我是发送端"; 17. byte[] buf=info2.getBytes(); 18. //指明接收端的IP和端口号。演练时请注意更换成实际IP 19. InetAddress ip=InetAddress.getByName("192.168.0.104"); 20. DatagramPacket pcket = new DatagramPacket(buf,buf.length,ip,3456); 21. socket.send(pcket);//从此套接字中发送数据 22. displayRecInfo(socket); //调用displayRecInfo()方法显示结果 23. } 24. catch(Exception ex) { 25. System.out.println(ex.toString()); 26. } 27. } 28. //用于在控制台中显示结果的diplayRecInfo()方法 29. public static void displayRecInfo(DatagramSocket s)throws IOException { 30. byte[] buffer =new byte[1024]; //定义用于存储数据的字节数组 31. DatagramPacket packet = new DatagramPacket(buffer,buffer.length); 32. s.receive(packet); 33. byte[] data = packet.getData(); 34. InetAddress ip=packet.getAddress(); 35. System.out.println("接收端的回应:"+new String(data)); 36. System.out.println("接收端的IP:"+ip.toString()); 37. System.out.println("接收端的端口:"+packet.getPort()); 38. } 39. }
接收端:
1. import java.io.IOException; 2. import java.net.DatagramPacket; 3. import java.net.DatagramSocket; 4. import java.net.InetAddress; 5. 6. public class SX10S { 7. static boolean isRun = true; 8. public static void main(String[] arg) { 9. System.out.println("-_接收端启动成功一 "); 10. try { 11. //演练时请注意将IP地址更换成实际IP 12. InetAddress ip = InetAddress.getByName("192.168.0.104"); 13. DatagramSocket socket = new DatagramSocket(3456,ip); 14. byte[] buf = new byte[1024]; 15. //创建接收数据包,数据存储在buf中 16. DatagramPacket packet1 = new DatagramPacket(buf, buf.length); 17. while(isRun) { //接收操作,接收端循环操作,跳出循环将停止接收信息 18. socket.receive(packet1); 19. System.out.println("---接收端收到数据一 "); 20. displayRecInfo(packet1); 21. String temp = ""; 22. byte[] d = packet1.getData(); 23. if(!new String(d).toString().trim().equals("bye")) { 24. //如果接收到的不是bye 25. temp = "我是接收端,你发送的数据以收到"; 26. }else { 27. temp = "好吧,再见"; 28. isRun = false; //若接收的信息是bye,则退出循环,不再接收数据 29. } 30. byte[] buffer = temp.getBytes(); 31. //创建数据报,指定需要反馈给发送者的SocketAddres地址 32. DatagramPacket packet2 = 33. new DatagramPacket(buffer, buffer.length, packet1.getSocketAddress()); 34. socket.send(packet2); 35. } 36. socket.close(); 37. } 38. catch(Exception ex) { 39. System.out.println(ex.toString()); 40. } 41. } 42. public static void displayRecInfo(DatagramPacket p) throws IOException{//显示数据的方法 43. byte[] data = p.getData(); 44. InetAddress ip = p.getAddress();//发送者的地址 45. //trim()方法用于除去空元素 46. System.out.println("收到的消息:" + new String(data).trim()); 47. System.out.println("发送者的IP:" + ip.toString()); 48. System.out.println("发送者的端口号:"+ p.getPort()); 49. } 50. }