• 1. 第8章网络功能
  • 2. 第8章网络功能8.1 Java与internet 8.2 使用URL 8.3 访问cgi 8.4 URL连接 8.5 Socket 8.6 internet应用 8.7 数据报 8.8 JDBC 8.9 小结2
  • 3. 8.1 Java与网络Java语言取得成功的领域之一就是网络 (其他语言)数页代码---->(Java)一条语句 TCP/IP(传输控制协议/网间协议)是internet的主要协议,定义了计算机和外设进行通信所使用的规则(应用层,传输层,网络层,链路层). 大多数基于internet的应用程序被看作TCP/IP协议的上一层. 如 : ftp, http, smtp, pop3, telnet, nntp等 IP地址:TCP/IP网络中的每台计算机都有唯一的地址--IP地址. 在Java中,有一个用来存储internet地址的类叫InetAddress.3
  • 4. 8.1 Java与网络例:获取本机的IP地址 import java.net.*; public class getLocalHostTest { public static void main() { InetAddress myIP=null; try {myIP=InetAddress.getLocalHost();} catch{UnknowHostException e){} System.out.println(myIP); } } 创建inetAddress类不用构造函数(不用new)4
  • 5. 8.1 Java与网络下面的例子演示java如何根据域名自动到DNS 上查找IP地址(与DNS服务器的连接减至一行) import java.net.*; public class getIP { public static void main(String args[]) { InetAddress pku=null; try{ pku= InetAddress.getByName(“www.pku.edu.cn”); }catch(UnknowHostException e) {} System.out.println(pku); } }5
  • 6. 8.1 Java与网络Java提供的网络功能有三大类: URL, Socket, Datagram. URL是三大功能中最高级的一种,通过URL Java程序可以直接送出或读入网络上的数据. Socket是传统网络程序最常用的方式,可以想象为两个不同的程序通过网络的通信信道. Datagram是更低级的网络传输方式,它把数据的目的纪录在数据包中,然后直接放在网络上.6
  • 7. URLJava 程序DataInputStream8.2 使用URL8.2.3 通过URL读取WWW服务器上的数据 将URL位置的数据转成一个数据流 URL url=new (http://www.pku.edu.cn/index.html” DataInputStream data=new DataInputStream(url.openStream()); 从数据流中读出数据 String line=data.readLine() while(line!=null) line=data.readLine()7
  • 8. 8.2 使用URL例:从给定的位置中读数据(ReadURLData.prj)http://www.pku.edu.cn/connect <...> actionURL urlButtonFrame主类str=a.getText()b=url.openStream()TextArea cline_str=b.readLine() c.appendText(line_str);TextField a URL url=new URL(str)DataInputStream b8
  • 9. 8.2 使用URLpublic boolean action(Event evt, Object arg) { try{ String line; String str=textfield.getText(); url=new URL(str); data=new DataInputStream(url.openStream()); while((line=data.readLine())!=null){ textarea.appendText(line); } data.close(); }catch(MalformedURLException me){ System.out.println("Error URL"); }catch(IOException ie){ System.out.println("Error IO"); } return true; } 9
  • 10. 欢迎来访,你是第 个来访者!127你是第个来访者客户端 HTML服务器端 CGI程序num++imgcgi程序名8.3 访问cgi起始页上的计数器及cgi程序(script)10
  • 11. 8.3 访问cgi
    sendresetYour name数据库 服务器Web服务器cgi程序form11
  • 12. 8.3 访问cgicgi(公共网关)程序可以用任何一种变成语言来写. cgi将web与外部程序连接起来(数据库查询等) cgi程序要放在指定的目录下cgi-bin目录. cgi通常以GET或POST接收数据,12
  • 13. 8.3 访问cgi从小应用中运行CGI程序(GET) Socket runcgi=new Socket(“www.jamsa.com”,80); OutputStream os=runcgi.getOutputStream(); PrintStream ps=new PringtStream(os); ps.println(“GET/cgi-bin/testcgi? arg1=val1& args2=val2&arg3=val3”); http://<机器名>/?<查询串>13
  • 14. 8.3 访问cgiget方法把数据作为命令行中的参数传递给此cgi (适用于少量参数的情况) Java cgi程序通过main方法的串参数接受命令行. C cgi程序通过访问环境变量中的查询串 QUERY_STRING,来获得查询串中的信息. 例如在C程序中: char *str; str=getevn(QUERY_STRING); 14
  • 15. 8.3 访问cgiimport java.io.*; import java.net.*; public class test_cgi { public static void main(String[] args) throws Exception { URL url = new URL ("http://pact518.hit.edu.cn/~wangqb/CGI- BIN/test_2.cgi?012345678"); URLConnection connection = url.openConnection(); } } #include "stdio.h” main() { char *Query_String; Query_String = getenv("QUERY_STRING"); /*treatment*/ }15
  • 16. 8.3 访问cgi从小程序中运行CGI程序(post) post方法通过标准输出向cgi传送参数(适合参数 较多的情况) 用post方法要有数据输出流 Socket runcgi=new Socket(“www.jamsa.com”,80); 建立socket连接 DataOutputStream ds=runcgi.getOutputStream(); 建立输入流 ds.println(“POST/cgi-bin/guestbook.pl”); 运行cgi程序16
  • 17. 8.3 访问cgi通知发送的数据类型 ds.println(“Content-type:plain/text”); 通知发送的数据长度 String data=“Hello world” ds.println(“Content-length”+data.length+”\n”); 发送数据 ds.println(data);17
  • 18. 8.3 访问cgicgi接收post方法送来的数据,就像从标准输入读数据一样. getchar();gets();(C语言的情况)(要建立数据流) cgi返回数据时要指明数据类型等信息: printf(“Content-type:text/plain\n\n”); 或 printf(“Content-type:text/html\n\n”); 或 printf(“Content-type:image/gif\n\n”); cgi规定服务器与外部程序交换信息的协议.18
  • 19. 8.3 访问cgiString count_srt URL url=new URL(“http://202.118.239.38/cgi-bin/count.cgi”); DataInputStream data=new DataInputStream(url.openStrean()); count_str=data.readLine();(此处读入的是cgi程序的输出) g.drawstring(“You are the “+count_str+ ”visitor”);返回结果DataInputStream客户端 java程序服务器端 cgi程序URL连接19
  • 20. 8.4 URL连接URL双向通信(URLConection) URLConnection是一个一http为中心的类 1. 建立连接 URL url=new URL(“http://www.yahoo.com/”); URLConnection con=url.openConnection(); 2. 向服务器端送数据 PrintStream outStream=new PrintStream(con.getOutputStream()); outStream.println(string_data); 20
  • 21. 8.4 URL连接3. 从服务器读数据 DataInputStream inStream=new DataInputStream(con.getInputStream()); inStream.readLine(); 从URL中得到的输出流通常与一个CGI程序结合一起工作客户端 java程序DataOutputStreamDataInputStreamCGI程序 STDINSTDOUT服务器 ( 排序 sort.cgi)connectiuongetchar()putchar()21
  • 22. 8.4 URL连接URLConnection同时支持get和post两种机制一般的格式. 缺省情况下位post method方式 URL和URLConnection的区别在于前者代表一个资源的位置,后者代表一种连接 下面的例子中Java程序访问cgi程序,并传给它10个数据,cgi程序胡接收后,排序,并传送回来. 连接的建立、数据流的建立、java如何发数据、如何接收数据、cgi程序如何发送和接收 22
  • 23. 8.4 URL连接import java.io.*; import java.net.*; public class test_cgi {public static void main(String[] args) throws Exception { URL url = new URL("http://pact518.hit.edu.cn/~wangqb/cgi-bin/test.cgi"); URLConnection connection = url.openConnection(); connection.setDoOutput(true); PrintStream out = new PrintStream(connection.getOutputStream()); out.println("0123456789"); out.close(); 23
  • 24. 8.4 URL连接DataInputStream in = new DataInputStream(connection.getInputStream()); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); System.in .read (); in.close();24
  • 25. 8.4 URL连接#include "stdio.h" main() { int array[10]; int i,j,k; printf("Content-type:text/plain\n\n"); for(i=0;i<=9;i++) array[i]=getchar(); //read data from InputStream for(i=0;i<=8;i++) { for(j=i;j<=9;j++) { if(array[i]
  • 26. 8.5 Socket8.3.1 什么是socket? Socket是网络上运行的程序之间双向通信链路的最后终结点网络服务Mailftpfinger20telnet数据结构I/O缓冲区端口2123客户程序SocketIP,portIP与端口的组合得出一个套接字,可以完全分辨internet上运行的程序26
  • 27. internet服务端口号端口号internet服务telnet 23 nntp 119ftp 21 www 80DNS 53 POP3 1108.5 Socket端口号:TCP/IP协议为每种服务定义了一个端口,当一台计算机上运行不同服务器程序时,,根据端口号不同提供相应的服务. 端口号不是计算机上的物理连接器,它只是具有软件意义的假想端口27
  • 28. 8.5 Socket在服务器端通过指定一个用来等待的连接的端口号创建一个 ServerSocket实例. 在客户端通过规定一个主机和端口号创建一个 socket实例,连到服务器上. ServerSocket类的accept方法使服务器处于阻塞状态,等待用户请求 Socket类和ServerSocket是基于TCP协议的,TCP协议提供64个端口,256以内位保留端口.28
  • 29. 8.5 Socket在本地机器上测试网络程序用回送地址Socket socket=new Socket(“127.0.0.1”,2525); 如果网络的一端已经关闭,另一端读到null. 建立socket连接后,还应该建立输入输出数据流.29
  • 30. 8.5 SocketServerServerSocket(port #)Server Socket.accept()Socket()OutputStreamInputStreamClose SocketClientSocket(host, port #)Attempt the connectionOutputStreamInputStreamClose Socket30
  • 31. 8.5 Socket下面的例子演示一个简单的服务器与客户的交互,即服务器等待,客户访问,相互通一次信息. 31
  • 32. 8.5 Socket. 8.5 Socket创建服务器(端口号)定义数据成员服务器等待 网络连接建立socket流读客户 端信息向用户发出一个字符串创建Socket实例定义数据成员建立socket流读socket流 (接收并显示)送用户名给 服务器关闭流waiting for user127.0.0.1 11111111login:connetcting client...java提示用户登录成功读socket流User :javaLogin successful32
  • 33. 8.5 Socket例:显示服务器与客户机间的通信(服务器端)PrintStream ps=null; DataInputStream dis=null; String username; ServerSocket serverSocket=null; Socket clientSocket=null;try { serverSocket=new ServerSocket(1111); }catch (IOException e) { System.out.println( “Error”+e); System.exit(1);}try { clientSocket=serverSocket.accept(); }catch (IOException e){ System.out.println("Accept failed.");System.exit(1);}创建服务器(端口号)定义数据成员服务器等待 网络连接33
  • 34. 8.5 Socket.ps=new PrintStream(clientSocket.getOutputStream()); dis=new DataInputStream(clientSocket.getInputStream()); 创建服务器(端口号)定义数据成员服务器等待 网络连接建立socket流向客户发出登录要求 ps.println("login:"); ps.flush();34
  • 35. 8.5 Socketps.println("login sucessful"); ps.flush(); System.out.println(username+" has logged off");}读客户 端信息创建服务器(端口号)定义数据成员服务器等待 网络连接建立socket流向用户发出登录要求通知客户连接完毕if ((username=dis.readLine())==null) { System.out.println("readLine returned null"); System.exit(1); } System.out.println("Username:"+username);35
  • 36. 8.5 Socket例:显示服务器与客户机间的通信(客户端)创建Socket实例PrintStream output; DataInputStream input; String string; Socket socket=null;定义数据成员try{socket=new Socket("127.0.0.1",1111); }catch(IOException e){ System.out.println("Error ”+e); return;} input=new DataInputStream(socket.getInputStream()); output=new PrintStream(socket.getOutputStream()); 建立socket流36
  • 37. . 8.5 Socket.System.out.println(input.readLine());创建Socket实例定义数据成员建立socket流读socket流 (看到提示)System.in.read(bArray); String s=new String(bArray,0); output.println(s);从键盘上读送用户 名送给服务器端关闭流socket.close(); input.close(); output.close(); System.out.println("Done");System.out.println(input.readLine()); System.out.print("Logging off...");读服务器反馈37
  • 38. . 8.5 Socket. 8.5 Socket创建服务器(端口号)定义数据成员服务器等待 网络连接建立socket流读客户 端信息向用户发送字符串创建Socket实例定义数据成员建立socket流读socket流 (看到提示)送用户名给 服务器关闭流waiting for user127.0.0.1 11111111login:connetcting client...java提示用户登录成功读socket流User :javaLogin successful38
  • 39. 8.5 Socket支持多客户 一种解决方案: 一台计算机上一次启动多个服务器程序,只要端口号不同.\myjava\clientAndServerTest myserver <-------->myclient----f8.bat myserver2<-------->myclient2----f9.batServer1(1111)client(2222)Server2(2222)client(1111)Computer 139
  • 40. 8.5 Socket第二种方案: (支持多客户) Server client1client2serverthreadserverthread将服务器写成多线程的,不同的线程为不同的客户服务. main()只负责循环等待 线程负责网络连接,接收客户输入的信息40
  • 41. 8.5 Socket.客户1客户2服务器线程()线程2线程( )线程( )41
  • 42. . 8.5 Socket创建服务器(端口号)定义数据成员服务器等待 网络连接建立socket流读客户 端信息提示用户输入客户名创建Socket实例定义数据成员建立socket流读socket流 (看到提示)送用户名给 服务器关闭流waiting for user127.0.0.1 11111111login:connetcting client...java提示用户登录成功读socket流User :javaLogin successful42
  • 43. 8.5 Socketpublic static void main(String args[]) {ServerSocket serverSocket=null; try{serverSocket=new ServerSocket(1111); }catch(Exception e){ System.out.println(”Error”+e);System.exit(1);} while(true) {Socket clientSocket=null; System.out.println("waiting for users..."); try { clientSocket=serverSocket.accept(); }catch(IOException e){ System.out.println("accept failed:"+e);} new serverThread(clientSocket).start(); }}43
  • 44. 8.5 Socketclass serverThread extends Thread { DataInputStream input; PrintStream output; String user; Socket clientSocket; serverThread(Socket clientSocket) { this.clientSocket=clientSocket; } public void run() { try{ input=new DataInputStream (clientSocket.getInputStream()); output=System.out; user=input.readLine(); System.out.println(user+" Connected!"); }catch(IOException e){ } try {while(true) { String string; if((string=input.readLine())==null) break; output.println(user+string); output.flush(); } }catch(Exception e){ return; } System.out.println(user+ "has disconnected."); try{ clientSocket.close(); input.close(); }catch(Exception e){ return; } }}44
  • 45. serverHello 1076Hello 1071abcWAIT GO…abcWAIT GO…defdef 8.5 Socket例:通过服务器交换信息(exchangebyserver)45
  • 46. 8.5 Socket.服务器 (1111) accept socket 客 户IP client1线程客 户IP client2线程服务器一端为了能接收多个客户的信息,它的输入流,输出流都是数组型的. ServerSocket.accept()等待用户连接,一旦连接上,则调用服务程序. 服务程序的主要内容是网络的读写,多客户的原因,网络读写的功能用多线程实现,因此将此部分功能单独分离出来,构成线程类 46
  • 47. 8.5 Socketclient1client2serviceRequestserverServerSocketSocketgetOutputStreamgetInputStreamreader.runreader.run服务器端accept()reader.start()read_net_inputwrite_net_output()47
  • 48. client()write.runwrite_net_output()read_net_input()close_server()客户端writer.start()paint()socketgetLocalPort()getInputStreamgetOutputStream服 务 器8.5 Socket48
  • 49. 8.7 DatagramTCP/IP传输层由两个并列的协议:TCP,UDP. 一般套接字(TCP)提供一个可靠的传输模型作为两个网络端点的字节流,有纠错能力. UDP没有保持的连接和数据流,数据报是一个网络上发送的独立信息,它的到达,到达时间,以及内容不能得到保证.socketserverclientdatagramserverclient49
  • 50. 8.7 DatagramTCP提供高可靠性服务,适用于一次要传输交换大量报文的情况,信道上传递的包不需要源地址和目的地址 UDP提供高效率服务,适用于依次传输交换少量报文的情形 (如数据库查询),每个数据包要包含目的地址和端口号. 数据报文的使用以包为中心:打包,拆包. Java.net包支持两种不同的在网络上送数据的方法:一般套接字和数据报文套接字. 50
  • 51. 8.7 Datagram发出报文的标准步骤如下: 1. 定义数据成员 DatagramSocket socket; DatagramPacket packet; InetAddress address;(用来存放接收方的地址) int port; ;(用来存放接收方的端口号) 2. 创建数据报文Socket对象 try {socket=new DatagramSocket(1111);} catch(java.net.SocketException e) {} socket 绑定到一个本地的可用端口,等待接收客户的请求.51
  • 52. 8.7 Datagram3.分配并填写数据缓冲区(一个字节类型的数组) byte[] Buf=new byte[256]; 存放从客户端接收的请求信息. 4.创建一个DatagramPacket packet=new DatagramPacket(buf, 256); 用来从socket接收数据,它只有两个参数 5. 服务器阻塞 socket.receive(packet); 在客户的请求报道来之前一直等待 52
  • 53. 8.7 Datagram6. 从到来的包中得到地址和端口号 InetAddress address=packet.getAddress(); int port=packet.getPort(); 7. 将数据送入缓冲区 或来自文件,或键盘输入 8. 建立报文包,用来从socket上发送信息 packet=new DatagramPacket (buf,buf.length, address,port); 9. 发送数据包 10.关闭socket socket.send(packet); socket.close();53
  • 54. 8.7 Datagram客户端接收包的步骤如下: 1. 定义数据成员 int port; InetAddress address; DatagramSocket socket; DatagramPacket packet; byte[] sendBuf=new byte[256]; 2. 建立socket socket=new DatagramSocket();54
  • 55. 8.7 Datagram3. 向服务器发出请求报文 address=InetAddress.getByName(args[0]); port=parseInt(args[1]); packet=new DatagramPacket(sendBuf,256,address,port); socket.send(packet); 这个包本身带有客户端的信息 4. 客户机等待应答 packet=new DatagramPacket(sendBuf,256); socket.receive(packet);(如果没有到就一直等待,因此实用程序要设置时间限度) 55
  • 56. 8.7 Datagram5. 处理接收到的数据 String received=new String(packet.getData(),0); System.out.println(received); 数据报套接字首先是强调发送方和接收方的区别,同时也指出服务器和客户之间的不同: 一个客户机必须事先知道服务器的地址和端口,以便进行出事连接 一个服务器从它接收到的数据报文中读取客户端的地址和端口.56
  • 57. 8.7 Datagram.建立数据报socket();建立一个报文包packet等待请求报文建立数据报socket建立一个请求包发出请求获得对方地址构成信息包发送出去创建接收包等待接收57
  • 58. 8.8 小结实现网络功能要靠URL类, URLConection类, Socket类和DatagramSocket类 网络上的数据传送是将网络连接转换成输入输出流 DataInputStream和DataOutputStream (PrintStream)是网间流的载体. URL适用于web应用,如访问http服务器是高层服务 URLConection的另一边通常是cgi程序 cgi程序完成客户端与外部程序的交互 58
  • 59. 8.6 小结向cgi传送数据有get和post两种方法 cgi通过访问环境变量或读标准输入获得数据 回绕地址可用于在本地机器上调试网络程序 Socket适用于面向连接的,可靠性要求高的应用 Datagram适用于效率要求高的应用 Socket是由IP和端口构成的一种网上通信链路的一端 Socket通信要分别运行服务器和客户程序 服务器程序是多线程的,可处理多个客户的请求 59
  • 60. 作业编写一个会话程序 要求: 会话双方可以自由通话,看到对方发来“bye”则退出60