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 小结,3,8.1 Java与网络,Java语言取得成功的领域之一就是网络(其他语言)数页代码-(Java)一条语句 TCP/IP(传输控制协议/网间协议)是internet的主要协议,定义了计算机和外设进行通信所使用的规则(应用层,传输层,网络层,链路层). 大多数基于internet的应用程序被看作TCP/IP协议的上一层. 如 : ftp,
2、http, smtp, pop3, telnet, nntp等 IP地址:TCP/IP网络中的每台计算机都有唯一的地址-IP地址. 在Java中,有一个用来存储internet地址的类叫InetAddress.,4,8.1 Java与网络,例:获取本机的IP地址 import .*; public class getLocalHostTest public static void main() InetAddress myIP=null;try myIP=InetAddress.getLocalHost();catchUnknowHostException e)System.out.print
3、ln(myIP); 创建inetAddress类不用构造函数(不用new),5,8.1 Java与网络,下面的例子演示java如何根据域名自动到DNS 上查找IP地址(与DNS服务器的连接减至一行) import .*; public class getIP public static void main(String args) InetAddress pku=null;try pku=InetAddress.getByName(“”);catch(UnknowHostException e) System.out.println(pku); ,6,8.1 Java与网络,Java提供的网络
4、功能有三大类: URL, Socket, Datagram. URL是三大功能中最高级的一种,通过URL Java程序可以直接送出或读入网络上的数据. Socket是传统网络程序最常用的方式,可以想象为两个不同的程序通过网络的通信信道. Datagram是更低级的网络传输方式,它把数据的目的纪录在数据包中,然后直接放在网络上.,7,8.2 使用URL,8.2.3 通过URL读取WWW服务器上的数据 将URL位置的数据转成一个数据流 URL url=new (http:/ DataInputStream data=newDataInputStream(url.openStream(); 从数据流
5、中读出数据 String line=data.readLine()while(line!=null) line=data.readLine(),8,8.2 使用URL,例:从给定的位置中读数据(ReadURLData.prj),http:/ 使用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.readLi
6、ne()!=null)textarea.appendText(line); data.close();catch(MalformedURLException me)System.out.println(“Error URL“);catch(IOException ie)System.out.println(“Error IO“);return true; ,10,你是第个来访者,8.3 访问cgi,起始页上的计数器及cgi程序(script),11,8.3 访问cgi,12,8.3 访问cgi,cgi(公共网关)程序可以用任何一种变成语言来写. cgi将web与外部程序连接起来(数据库查询等)
7、 cgi程序要放在指定的目录下cgi-bin目录. cgi通常以GET或POST接收数据,13,8.3 访问cgi,从小应用中运行CGI程序(GET)Socket runcgi=new Socket(“”,80); OutputStream os=runcgi.getOutputStream();PrintStream ps=new PringtStream(os);ps.println(“GET/cgi-bin/testcgi? arg1=val1 http:/?,14,8.3 访问cgi,get方法把数据作为命令行中的参数传递给此cgi (适用于少量参数的情况) Java cgi程序通过m
8、ain方法的串参数接受命令行. C cgi程序通过访问环境变量中的查询串 QUERY_STRING,来获得查询串中的信息. 例如在C程序中: char *str; str=getevn(QUERY_STRING);,15,8.3 访问cgi,import java.io.*; import .*; public class test_cgi public static void main(String args) throws Exception URL url = new URL(“http:/ URLConnection connection = url.openConnection();
9、 #include “stdio.h” main() char *Query_String;Query_String = getenv(“QUERY_STRING“);/*treatment*/ ,16,8.3 访问cgi,从小程序中运行CGI程序(post) post方法通过标准输出向cgi传送参数(适合参数较多的情况) 用post方法要有数据输出流 Socket runcgi=new Socket(“”,80); 建立socket连接 DataOutputStream ds=runcgi.getOutputStream(); 建立输入流 ds.println(“POST/cgi-bin/g
10、uestbook.pl”); 运行cgi程序,17,8.3 访问cgi,通知发送的数据类型 ds.println(“Content-type:plain/text”); 通知发送的数据长度 String data=“Hello world” ds.println(“Content-length”+data.length+”n”); 发送数据 ds.println(data);,18,8.3 访问cgi,cgi接收post方法送来的数据,就像从标准输入读数据一样. getchar();gets();(C语言的情况)(要建立数据流) cgi返回数据时要指明数据类型等信息:printf(“Conte
11、nt-type:text/plainnn”); 或 printf(“Content-type:text/htmlnn”); 或 printf(“Content-type:image/gifnn”); cgi规定服务器与外部程序交换信息的协议.,19,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();(此处读
12、入的是cgi程序的输出) g.drawstring(“You are the “+count_str+ ”visitor”);,20,8.4 URL连接,URL双向通信(URLConection) URLConnection是一个一http为中心的类1. 建立连接URL url=new URL(“http:/ con=url.openConnection();2. 向服务器端送数据PrintStream outStream=new PrintStream(con.getOutputStream();outStream.println(string_data);,21,8.4 URL连接,3.
13、从服务器读数据DataInputStream inStream=new DataInputStream(con.getInputStream();inStream.readLine(); 从URL中得到的输出流通常与一个CGI程序结合一起工作,客户端,java程序,DataOutputStream,DataInputStream,CGI程序,STDIN,STDOUT,服务器,( 排序sort.cgi),connectiuon,getchar(),putchar(),22,8.4 URL连接,URLConnection同时支持get和post两种机制一般的格式. 缺省情况下位post metho
14、d方式 URL和URLConnection的区别在于前者代表一个资源的位置,后者代表一种连接 下面的例子中Java程序访问cgi程序,并传给它10个数据,cgi程序胡接收后,排序,并传送回来. 连接的建立、数据流的建立、java如何发数据、如何接收数据、cgi程序如何发送和接收,23,8.4 URL连接,import java.io.*; import .*; public class test_cgi public static void main(String args) throws Exception URL url = new URL(“http:/ URLConnection co
15、nnection = url.openConnection(); connection.setDoOutput(true);PrintStream out = new PrintStream(connection.getOutputStream(); out.println(“0123456789“);out.close();,24,8.4 URL连接,DataInputStream in = new DataInputStream(connection.getInputStream(); String inputLine; while (inputLine = in.readLine() !
16、= null) System.out.println(inputLine); System.in .read (); in.close();,25,8.4 URL连接,#include “stdio.h“ main() int array10; int i,j,k;printf(“Content-type:text/plainnn“);for(i=0;i=9;i+)arrayi=getchar(); /read data from InputStreamfor(i=0;i=8;i+) for(j=i;j=9;j+) if(arrayiarrayj) k=arrayj; arrayj=array
17、i; arrayi=k; printf(“nOutput number!n“);for(i=0;i=9;i+) printf(“%c“,arrayi); /write data to OutputStream ,26,8.5 Socket,8.3.1 什么是socket? Socket是网络上运行的程序之间双向通信链路的最后终结点,IP与端口的组合得出一个套接字,可以完全分辨internet上运行的程序,27,8.5 Socket,端口号:TCP/IP协议为每种服务定义了一个端口,当一台计算机上运行不同服务器程序时,根据端口号不同提供相应的服务. 端口号不是计算机上的物理连接器,它只是具有软件
18、意义的假想端口,28,8.5 Socket,在服务器端通过指定一个用来等待的连接的端口号创建一个 ServerSocket实例. 在客户端通过规定一个主机和端口号创建一个 socket实例,连到服务器上. ServerSocket类的accept方法使服务器处于阻塞状态,等待用户请求 Socket类和ServerSocket是基于TCP协议的,TCP协议提供64个端口,256以内位保留端口.,29,8.5 Socket,在本地机器上测试网络程序用回送地址Socket socket=new Socket(“127.0.0.1”,2525); 如果网络的一端已经关闭,另一端读到null. 建立so
19、cket连接后,还应该建立输入输出数据流.,30,8.5 Socket,31,8.5 Socket,下面的例子演示一个简单的服务器与客户的交互,即服务器等待,客户访问,相互通一次信息.,32,8.5 Socket,. 8.5 Socket,创建服务器(端口号),定义数据成员,服务器等待 网络连接,建立socket流,读客户 端信息,向用户发出一个字符串,创建Socket实例,定义数据成员,建立socket流,读socket流 (接收并显示),送用户名给 服务器,关闭流,waiting for user,127.0.0.1 1111,1111,login:,connetcting client.
20、,java,提示用户登录成功,读socket流,User :java,Login successful,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”
21、+e); System.exit(1);,try clientSocket=serverSocket.accept(); catch (IOException e)System.out.println(“Accept failed.“);System.exit(1);,创建服务器(端口号),定义数据成员,服务器等待 网络连接,34,8.5 Socket,.,ps=new PrintStream(clientSocket.getOutputStream(); dis=new DataInputStream(clientSocket.getInputStream();,建立socket流,向客户发
22、出登录要求,ps.println(“login:“); ps.flush();,35,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);,3
23、6,8.5 Socket,例:显示服务器与客户机间的通信(客户端),创建Socket实例,PrintStream output; DataInputStream input; String string; Socket socket=null;,定义数据成员,trysocket=new Socket(“127.0.0.1“,1111); catch(IOException e)System.out.println(“Error ”+e); return;,input=new DataInputStream(socket.getInputStream(); output=new PrintStr
24、eam(socket.getOutputStream();,建立socket流,37,. 8.5 Socket,.,System.out.println(input.readLine();,读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(
25、input.readLine(); System.out.print(“Logging off.“);,读服务器反馈,38,. 8.5 Socket,. 8.5 Socket,创建服务器(端口号),定义数据成员,服务器等待 网络连接,建立socket流,读客户 端信息,向用户发送字符串,创建Socket实例,定义数据成员,建立socket流,读socket流 (看到提示),送用户名给 服务器,关闭流,waiting for user,127.0.0.1 1111,1111,login:,connetcting client.,java,提示用户登录成功,读socket流,User :java,
26、Login successful,39,8.5 Socket,支持多客户 一种解决方案: 一台计算机上一次启动多个服务器程序,只要端口号不同.myjavaclientAndServerTest myserver myclient-f8.bat myserver2myclient2-f9.bat,40,8.5 Socket,第二种方案: (支持多客户),Server,client1,client2,serverthread,serverthread,将服务器写成多线程的,不同的线程为不同的客户服务. main()只负责循环等待 线程负责网络连接,接收客户输入的信息,41,8.5 Socket,.
27、,客户1,客户2,服务器,线程(),线程2,42,43,8.5 Socket,public static void main(String args) ServerSocket serverSocket=null;tryserverSocket=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 clientSoc
28、ket=serverSocket.accept();catch(IOException e)System.out.println(“accept failed:“+e);new serverThread(clientSocket).start(); ,44,8.5 Socket,class serverThread extends Thread DataInputStream input; PrintStream output;String user; Socket clientSocket;serverThread(Socket clientSocket) this.clientSocket
29、=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.f
30、lush(); catch(Exception e) return; System.out.println(user+ “has disconnected.“);try clientSocket.close(); input.close();catch(Exception e) return; ,45,server,Hello 1076,Hello 1071,abc,WAIT GOabc,WAIT GOdef,def,8.5 Socket,例:通过服务器交换信息(exchangebyserver),46,8.5 Socket,.,服务器 (1111)accept socket,客 户,IP c
31、lient1,线程,客 户,IP client2,线程,服务器一端为了能接收多个客户的信息,它的输入流,输出流都是数组型的. ServerSocket.accept()等待用户连接,一旦连接上,则调用服务程序. 服务程序的主要内容是网络的读写,多客户的原因,网络读写的功能用多线程实现,因此将此部分功能单独分离出来,构成线程类,47,8.5 Socket,client1,client2,serviceRequest,server,ServerSocket,Socket,getOutputStream,getInputStream,reader.run,reader.run,服务器端,accept
32、(),reader.start(),read_net_input,write_net_output(),48,client(),write.run,write_net_output(),read_net_input(),close_server(),客户端,writer.start(),paint(),socket,getLocalPort(),getInputStream,getOutputStream,服 务 器,8.5 Socket,49,8.7 Datagram,TCP/IP传输层由两个并列的协议:TCP,UDP. 一般套接字(TCP)提供一个可靠的传输模型作为两个网络端点的字节流,有
33、纠错能力. UDP没有保持的连接和数据流,数据报是一个网络上发送的独立信息,它的到达,到达时间,以及内容不能得到保证.,socket,server,client,datagram,server,client,50,8.7 Datagram,TCP提供高可靠性服务,适用于一次要传输交换大量报文的情况,信道上传递的包不需要源地址和目的地址 UDP提供高效率服务,适用于依次传输交换少量报文的情形 (如数据库查询),每个数据包要包含目的地址和端口号. 数据报文的使用以包为中心:打包,拆包. J包支持两种不同的在网络上送数据的方法:一般套接字和数据报文套接字.,51,8.7 Datagram,发出报文的
34、标准步骤如下: 1. 定义数据成员DatagramSocket socket;DatagramPacket packet;InetAddress address;(用来存放接收方的地址)int port; ;(用来存放接收方的端口号) 2. 创建数据报文Socket对象try socket=new DatagramSocket(1111);catch(.SocketException e) socket 绑定到一个本地的可用端口,等待接收客户的请求.,52,8.7 Datagram,3.分配并填写数据缓冲区(一个字节类型的数组)byte Buf=new byte256; 存放从客户端接收的请求
35、信息. 4.创建一个DatagramPacketpacket=new DatagramPacket(buf, 256);用来从socket接收数据,它只有两个参数5. 服务器阻塞socket.receive(packet);在客户的请求报道来之前一直等待,53,8.7 Datagram,6. 从到来的包中得到地址和端口号InetAddress address=packet.getAddress();int port=packet.getPort(); 7. 将数据送入缓冲区或来自文件,或键盘输入 8. 建立报文包,用来从socket上发送信息packet=new DatagramPacket
36、(buf,buf.length, address,port); 9. 发送数据包 10.关闭socketsocket.send(packet); socket.close();,54,8.7 Datagram,客户端接收包的步骤如下: 1. 定义数据成员int port; InetAddress address;DatagramSocket socket;DatagramPacket packet;byte sendBuf=new byte256; 2. 建立socketsocket=new DatagramSocket();,55,8.7 Datagram,3. 向服务器发出请求报文addr
37、ess=InetAddress.getByName(args0);port=parseInt(args1);packet=new DatagramPacket(sendBuf,256,address,port);socket.send(packet);这个包本身带有客户端的信息 4. 客户机等待应答packet=new DatagramPacket(sendBuf,256);socket.receive(packet);(如果没有到就一直等待,因此实用程序要设置时间限度),56,8.7 Datagram,5. 处理接收到的数据String received=new String(packet.
38、getData(),0); System.out.println(received);数据报套接字首先是强调发送方和接收方的区别,同时也指出服务器和客户之间的不同: 一个客户机必须事先知道服务器的地址和端口,以便进行出事连接 一个服务器从它接收到的数据报文中读取客户端的地址和端口.,57,8.7 Datagram,.,建立数据报socket();,建立一个报文包packet,等待请求报文,建立数据报socket,建立一个请求包,发出请求,获得对方地址,构成信息包,发送出去,创建接收包,等待接收,58,8.8 小结,实现网络功能要靠URL类, URLConection类, Socket类和Dat
39、agramSocket类 网络上的数据传送是将网络连接转换成输入输出流 DataInputStream和DataOutputStream (PrintStream)是网间流的载体. URL适用于web应用,如访问http服务器是高层服务 URLConection的另一边通常是cgi程序 cgi程序完成客户端与外部程序的交互,59,8.6 小结,向cgi传送数据有get和post两种方法 cgi通过访问环境变量或读标准输入获得数据 回绕地址可用于在本地机器上调试网络程序 Socket适用于面向连接的,可靠性要求高的应用 Datagram适用于效率要求高的应用 Socket是由IP和端口构成的一种网上通信链路的一端 Socket通信要分别运行服务器和客户程序 服务器程序是多线程的,可处理多个客户的请求,60,作业,编写一个会话程序 要求: 会话双方可以自由通话,看到对方发来“bye”则退出,