600 likes | 753 Views
第 8 章网络功能. 北京大学计算机系 代亚非. 第 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 小结. 8.1 Java 与网络. Java 语言取得成功的领域之一就是网络 ( 其他语言 ) 数页代码 ---->(Java) 一条语句
E N D
第8章网络功能 北京大学计算机系 代亚非
第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 小结
8.1 Java与网络 • Java语言取得成功的领域之一就是网络 • (其他语言)数页代码---->(Java)一条语句 • TCP/IP(传输控制协议/网间协议)是internet的主要协议,定义了计算机和外设进行通信所使用的规则(应用层,传输层,网络层,链路层). • 大多数基于internet的应用程序被看作TCP/IP协议的上一层. 如 : ftp, http, smtp, pop3, telnet, nntp等 • IP地址:TCP/IP网络中的每台计算机都有唯一的地址--IP地址. • 在Java中,有一个用来存储internet地址的类叫InetAddress.
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)
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); } }
8.1 Java与网络 • Java提供的网络功能有三大类: URL, Socket, Datagram. • URL是三大功能中最高级的一种,通过URL Java程序可以直接送出或读入网络上的数据. • Socket是传统网络程序最常用的方式,可以想象为两个不同的程序通过网络的通信信道. • Datagram是更低级的网络传输方式,它把数据的目的纪录在数据包中,然后直接放在网络上.
DataInputStream URL Java 程序 8.2 使用URL • 8.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()
TextField a Frame主类 TextArea c str=a.getText() action line_str=b.readLine() c.appendText(line_str); Button URL url=new URL(str) URL url DataInputStream b b=url.openStream() 8.2 使用URL http://www.pku.edu.cn/ <html> <head><title><...></title></head> <body> 例:从给定的位置中读数据(ReadURLData.prj) connect
8.2 使用URL public 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; }
欢迎来访,你是第 个来访者! 1 2 7 客户端 服务器端 CGI程序 HTML cgi程序名 num++ img 8.3 访问cgi • 起始页上的计数器及cgi程序(script) 你是第<img SRC=“/cgi-bin/perl/counter.cgi”>个来访者
Your name Web服务器 form 数据库 服务器 cgi程序 send reset 8.3 访问cgi <form action="/scripts/test/query.idc" method=get> <form action="/scripts/test/query.idc" method=post>
8.3 访问cgi • cgi(公共网关)程序可以用任何一种变成语言来写. • cgi将web与外部程序连接起来(数据库查询等) • cgi程序要放在指定的目录下cgi-bin目录. • cgi通常以GET或POST接收数据,
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://<机器名>/<cgi程序路径>?<查询串>
8.3 访问cgi • get方法把数据作为命令行中的参数传递给此cgi (适用于少量参数的情况) • Java cgi程序通过main方法的串参数接受命令行. • C cgi程序通过访问环境变量中的查询串 QUERY_STRING,来获得查询串中的信息. • 例如在C程序中: char *str; • str=getevn(QUERY_STRING);
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_2.cgi?012345678"); URLConnection connection = url.openConnection(); } } #include "stdio.h” main() { char *Query_String; Query_String = getenv("QUERY_STRING"); /*treatment*/ } 8.3 访问cgi
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程序
8.3 访问cgi • 通知发送的数据类型 • ds.println(“Content-type:plain/text”); • 通知发送的数据长度 • String data=“Hello world” • ds.println(“Content-length”+data.length+”\n”); • 发送数据 • ds.println(data);
8.3 访问cgi • cgi接收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规定服务器与外部程序交换信息的协议.
客户端 服务器端 URL连接 cgi程序 java程序 DataInputStream 返回结果 8.3 访问cgi String 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”);
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);
8.4 URL连接 3. 从服务器读数据 DataInputStream inStream=new DataInputStream(con.getInputStream()); inStream.readLine(); • 从URL中得到的输出流通常与一个CGI程序结合一起工作 STDIN 客户端 服务器 CGI程序 DataOutputStream getchar() connectiuon ( 排序 sort.cgi) java程序 putchar() DataInputStream STDOUT
8.4 URL连接 • URLConnection同时支持get和post两种机制一般的格式. • 缺省情况下位post method方式 • URL和URLConnection的区别在于前者代表一个资源的位置,后者代表一种连接 • 下面的例子中Java程序访问cgi程序,并传给它10个数据,cgi程序胡接收后,排序,并传送回来. • 连接的建立、数据流的建立、java如何发数据、如何接收数据、cgi程序如何发送和接收
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();
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();
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]<array[j]) { k=array[j]; array[j]=array[i]; array[i]=k; } } } printf("\nOutput number!\n"); for(i=0;i<=9;i++) { printf("%c",array[i]); } //write data to OutputStream }
网络服务 IP,port ftp 20 telnet 21 客户程序 Socket 23 Mail finger 数据结构 I/O缓冲区 端口 8.5 Socket 8.3.1 什么是socket? • Socket是网络上运行的程序之间双向通信链路的最后终结点 IP与端口的组合得出一个套接字,可以完全分辨internet上运行的程序
端口号 internet服务 internet服务 端口号 ftp 21 www 80 telnet 23 nntp 119 DNS 53 POP3 110 8.5 Socket • 端口号:TCP/IP协议为每种服务定义了一个端口,当一台计算机上运行不同服务器程序时,,根据端口号不同提供相应的服务. • 端口号不是计算机上的物理连接器,它只是具有软件意义的假想端口
8.5 Socket • 在服务器端通过指定一个用来等待的连接的端口号创建一个 ServerSocket实例. • 在客户端通过规定一个主机和端口号创建一个 socket实例,连到服务器上. • ServerSocket类的accept方法使服务器处于阻塞状态,等待用户请求 • Socket类和ServerSocket是基于TCP协议的,TCP协议提供64个端口,256以内位保留端口.
8.5 Socket • 在本地机器上测试网络程序用回送地址Socket socket=new Socket(“127.0.0.1”,2525); • 如果网络的一端已经关闭,另一端读到null. • 建立socket连接后,还应该建立输入输出数据流.
Client Server Socket(host, port #) ServerSocket(port #) Attempt the connection Server Socket.accept() Socket() OutputStream OutputStream InputStream InputStream Close Socket Close Socket 8.5 Socket
8.5 Socket • 下面的例子演示一个简单的服务器与客户的交互,即服务器等待,客户访问,相互通一次信息.
. 8.5 Socket 定义数据成员 定义数据成员 8.5 Socket 1111 创建Socket实例 创建服务器(端口号) waiting for user 127.0.0.1 1111 服务器等待 网络连接 建立socket流 读socket流 (接收并显示) 建立socket流 connetcting client... login: 向用户发出一个字符串 送用户名给 服务器 java 读客户 端信息 User :java 读socket流 Login successful 提示用户登录成功 关闭流
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);}
定义数据成员 创建服务器(端口号) 服务器等待 网络连接 8.5 Socket • . 建立socket流 向客户发出登录要求 ps=new PrintStream(clientSocket.getOutputStream()); dis=new DataInputStream(clientSocket.getInputStream()); ps.println("login:"); ps.flush();
定义数据成员 创建服务器(端口号) 服务器等待 网络连接 向用户发出登录要求 建立socket流 8.5 Socket ps.println("login sucessful"); ps.flush(); System.out.println(username+" has logged off");} 读客户 端信息 通知客户连接完毕 if ((username=dis.readLine())==null) { System.out.println("readLine returned null"); System.exit(1); } System.out.println("Username:"+username);
8.5 Socket • 例:显示服务器与客户机间的通信(客户端) PrintStream output; DataInputStream input; String string; Socket socket=null; 定义数据成员 创建Socket实例 建立socket流 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实例 建立socket流 . 8.5 Socket System.out.println(input.readLine()); • . System.in.read(bArray); String s=new String(bArray,0); output.println(s); System.out.println(input.readLine()); System.out.print("Logging off..."); 读socket流 (看到提示) 从键盘上读送用户 名送给服务器端 socket.close(); input.close(); output.close(); System.out.println("Done"); 读服务器反馈 关闭流
. 8.5 Socket 定义数据成员 定义数据成员 . 8.5 Socket 1111 创建Socket实例 创建服务器(端口号) waiting for user 127.0.0.1 1111 服务器等待 网络连接 建立socket流 读socket流 (看到提示) 建立socket流 connetcting client... login: 向用户发送字符串 送用户名给 服务器 java 读客户 端信息 User :java 读socket流 Login successful 提示用户登录成功 关闭流
Server1(1111) client(1111) Server2(2222) client(2222) Computer 1 8.5 Socket • 支持多客户 • 一种解决方案: • 一台计算机上一次启动多个服务器程序,只要端口号不同.\myjava\clientAndServerTest • myserver <-------->myclient----f8.bat • myserver2<-------->myclient2----f9.bat
8.5 Socket serverthread • 第二种方案: • (支持多客户) serverthread Server client1 client2 将服务器写成多线程的,不同的线程为不同的客户服务. main()只负责循环等待 线程负责网络连接,接收客户输入的信息
线程( ) 线程( ) 8.5 Socket • . 服务器 客户1 线程() 客户2 线程2
. 8.5 Socket 定义数据成员 定义数据成员 1111 创建Socket实例 创建服务器(端口号) waiting for user 127.0.0.1 1111 服务器等待 网络连接 建立socket流 读socket流 (看到提示) 建立socket流 connetcting client... login: 提示用户输入客户名 送用户名给 服务器 java 读客户 端信息 User :java 读socket流 Login successful 提示用户登录成功 关闭流
8.5 Socket public 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(); }}
class 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; } }} 8.5 Socket
8.5 Socket • 例:通过服务器交换信息(exchangebyserver) Hello 1076 Hello 1071 abc def server WAIT GO…def WAIT GO…abc
8.5 Socket 服务器 (1111) accept socket • . IP client1 IP client2 客 户 客 户 线程 线程 服务器一端为了能接收多个客户的信息,它的输入流,输出流都是数组型的. ServerSocket.accept()等待用户连接,一旦连接上,则调用服务程序. 服务程序的主要内容是网络的读写,多客户的原因,网络读写的功能用多线程实现,因此将此部分功能单独分离出来,构成线程类
8.5 Socket • 服务器端 ServerSocket server Socket client1 accept() client2 serviceRequest read_net_input getInputStream write_net_output() getOutputStream reader.start() reader.run reader.run
8.5 Socket socket client() 客户端 getInputStream getOutputStream getLocalPort() writer.start() 服 务 器 write_net_output() write.run read_net_input() paint() close_server()
8.7 Datagram • TCP/IP传输层由两个并列的协议:TCP,UDP. • 一般套接字(TCP)提供一个可靠的传输模型作为两个网络端点的字节流,有纠错能力. • UDP没有保持的连接和数据流,数据报是一个网络上发送的独立信息,它的到达,到达时间,以及内容不能得到保证. socket client server datagram server client
8.7 Datagram • TCP提供高可靠性服务,适用于一次要传输交换大量报文的情况,信道上传递的包不需要源地址和目的地址 • UDP提供高效率服务,适用于依次传输交换少量报文的情形 (如数据库查询),每个数据包要包含目的地址和端口号. • 数据报文的使用以包为中心:打包,拆包. • Java.net包支持两种不同的在网络上送数据的方法:一般套接字和数据报文套接字.