• 1. 网络编程
  • 2. 提问URL的作用 如何使服务器端程序在某一端口监听 端口的范围,系统预留端口的范围
  • 3. 学习目标掌握Socket通信
  • 4. 本课内容使用java.net包中的类实现网络通信 -- URL类及其用法 -- Socket通信
  • 5. 两台计算机通过网络进行通信AB网络192.168.0.118192.168.0.10协议协议端口端口
  • 6. 1. TCP/IP协议TCP/IP指以TCP和IP为基础的不同层次上多个协议的集合。TCP:Transmission Control Protocol ;IP : Internet Protocol Telnet 远程登录。 FTP 文件传输协议。 SMTP 简单邮件传送协议。 SNMP 简单网络管理协议。
  • 7. 对等通信示例“你好”“Hello”传真中国教师翻译秘书“Hallo”“Hello”传真德国教师翻译秘书对交谈内容的共识用英语对话使用传真通信P3P2P1物理通信线路
  • 8. 2. IP地址为实现网络中不同计算机之间的通信,每台机器都必须有一个与众不同的标识---IP地址:; IP地址格式:数字型,32位,由4个 8位的二进制数组成,每8位之间用圆点隔开,如:192.168.0.1;
  • 9. DNS(域名系统)用于主机名称IP地址的转换
  • 10. 一台机器只通过一条链路连接到网络上,但一台机器中往往有很多应用程序需要进行网络通信,如何区分呢?这就要靠网络端口号(port)了。 端口号是一个标记机器的逻辑通信信道的正整数,端口号不是物理实体。IP地址和端口号组成了所谓的Socket,Socket是网络上运行的程序之间双向通信链路的最后终结点,它是TCP和UDP的基础。网络服务httpftp其他服务23telnet数据结构 I/O缓冲区端口2180客户程序SocketIP,portIP与端口号组合而得出的Socket,可以完全分辨Internet上运行的程序。3. 端口Port
  • 11. 端口号是用一个16位的整数来表达的,其范围为0~65535,其中0~1023为系统所保留,专门给那些通用的服务(well-known services),如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口为23,…因此,当我们编写通信程序时,应选择一个大于1023的数作为端口号,以免发生冲突。
  • 12. TCP协议传输层通常以TCP和UDP协议来控制端点到端点的通信。用于通信的端点是由Socket来定义的,Socket是由IP地址和端口号组成的。 传输控制协议(TCP)是在端点与端点之间建立持续的连接而进行通信。 TCP协议具有可靠性和有序性,并且以字节流的方式发送数据。
  • 13. UDP协议与TCP协议不同,用户数据报协议(UDP)则是一种无连接的传输协议。利用UDP协议进行数据传输时,首先需要将要传输的数据定义成数据报(Datagram),在数据报中指明数据所要达到的Socket(主机地址和端口号),然后再将数据报发送出去。这种传输方式是无序的,也不能确保绝对的安全可靠,但它很简单也具有比较高的效率,这与通过邮局发送邮件的情形非常相似。 TCP协议和UDP协议各有各的用处。当对所传输的数据具有时序性和可靠性等要求时,应使用TCP协议;当传输的数据比较简单、对时序等无要求时,UDP协议能发挥更好的作用。
  • 14. Java中的网络支持针对网络通信的不同层次,Java提供的网络功能有四大类:InetAddress 、URL、Sockets、Datagram。 InetAddress,用于标识网络上的硬件资源。 URL,通过URL,Java程序可以直接送出或读入网络上的数据。 Sockets和Datagram面向的则是传输层。Sockets使用的是TCP协议,这是传统网络程序最常用的方式,可以想象为两个不同的程序通过网络的通信信道进行通信。Datagram则使用UDP协议,是另一种网络传输方式,它把数据的目的地纪录在数据包中,然后直接放在网络上。
  • 15. java.net包中的主要的类和可能产生的例外包括: 面向IP层的类:InetAddress 面向应用层的类:URL、URLConnection 面向网络层的类: TCP协议相关类:Socket、ServerSocket UDP协议相关类:DatagramPacket、DatagramSocket、 可能产生的例外: BindException、ConnectException、MalformedURLException、NoRouteToHostException、ProtocolException、SocketException、UnknownHostException、UnknownServiceException
  • 16. 使用InetAddress类InetAddress可以用于标识网络上的硬件资源,它提供了一系列方法以描述、获取及使用网络资源。 InetAddress类没有构造函数,不能用new来构造一个InetAddress实例。通常是用它提供的静态方法来获取: public static InetAddress getByName(String host) :host可以是一个机器名,也可以是一个形如“%d.%d.%d.%d”的IP地址或一个DSN域名。 public static InetAddress getLocalHost() 方法通常会产生UnknownHostException例外,应在程序中捕获处理。 以下是InetAddress类的几个主要方法: public byte[] getAddress():获得本对象的IP地址 public String getHostAddress():获得本对象的IP地址“%d.%d.%d.%d” public String getHostName():获得本对象的机器名。
  • 17. InetAddress应用通过InetAddress,可以获取本机的IP地址 InetAddress myIP = InetAddress.getLocalHost(); System.out.println(myIP); 根据域名解析出IP地址 InetAddress jlonline = InetAddress.getByName(“www.jlonline.com”); System.out.println(jlonline); 示例
  • 18. InetAddress示例
  • 19. 3. URLURL(Uniform Resource Locator)是统一资源定位器的简称,表示Internet上某一资源的地址。 Internet上的资源包括HTML文件、图象文件、声音文件、动画文件以及其他任何内容 通过URL,就可以访问Internet。浏览器或其他程序通过解析给定的URL就可以在网络上查找相应的文件或其他资源。 一个URL包括两部分内容:协议名称和资源名称,中间用冒号隔开: Protocol:resourceName 如:http://gis.pku.edu.cn 协议名称指的是获取资源时所使用的应用层协议,如http,ftp,file等 资源名称则是资源的完整地址,包括主机名、端口号、文件名或文件内部的一个引用。当然,并不是所有的URL都必须包含这些内容。 http://www.ccit.js.cn http://www. ccit.js.cn/javaCourse/index.html ftp://www. ccit.js.cn/javaCourse/Techdoc/ch1.ppt http://www.abc.com:8080/java/network.html#UDP 相对URL: /abc.txt
  • 20. URL构造方法在java.net包中,提供了类URL来表示URL。类URL提供了很多构造方法来生成一个URL对象: public URL(String spec) public URL(URL context, String spec) public URL(String protocol, String host, String file) public URL(String protocol, String host, int port, String file) 以下是一些具体的构造实例: URL url1 = new URL(“http://www.ccit.js.cn”); URL base = new URL(“http://sc.pku.edu.cn”); URL url2 = new URL(base, “mywork1.html”); URL url3 = new URL(base, “mywork2.html”); URL url4 = new URL(“http”, “home.ccit.js.cn”,“/~lyw/test.html”); URL url5 = new URL(“http”, “www.abc.com”, 8080, “/java/network.html”); 当创建URL时发生错误,系统会产生例外MalformedURLException,这是非运行时例外,必须在程序中捕获处理。
  • 21. URL基本方法一个URL对象生成后,其属性是不能被改变的,但可以通过它给定的方法来获取这些属性: public String getProtocol():获取该URL的协议名 public String getHost() :获取该URL的主机名 public String getPort() :获取该URL的端口号 public String getPath() :获取该URL的文件路径 public String getFile() :获取该URL的文件名 public String getRef() :获取该URL在文件中的相对位置 public String getQuery() :获取该URL的查询名 示例1 示例2
  • 22. URL示例public class URLTest { public static void main(String[] args) { URL url = null; try { url = new URL("http://www.163.com/fff/java.html"); } catch(MalformedURLException e) { System.out.println("MalformedURLException: "+e); } System.out.println("The URL is:"); System.out.println(url); System.out.println("Use toString(): "+url.toString()); System.out.println("Protocol is: "+ url.getProtocol()); System.out.println("Host is: "+url.getHost()); System.out.println("Port is: "+url.getPort()); System.out.println("File is: "+url.getFile()); } }
  • 23. 使用URL ——通过URL读取www信息 通过URL类提供的方法openStream(),就可以读取一个URL对象所指定的资源。 public final InputStream openStream() 方法openStream()与指定的URL建立连接并返回一个InputStream对象,将URL位置的资源转成一个数据流。通过这个InputStream对象,就可以读取资源中的数据。URLJava 程序InputStream
  • 24. 实例读取网页import java.io.*; import java.net.*; public class URLReader{ public static void main(String args[]){ try{ URL u = new URL("http://www.cctu.cn/123.html"); BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream())); String s; while((s = in.readLine())!=null) System.out.println(s); in.close(); }catch(MalformedURLException e) { System.out.println(e); }catch(IOException e){ System.out.println(e); } } }
  • 25. 实例二下载文件练习简单的下载 实现多线程下载 1 可同时下载多个文件 2 下载一个文件的时候使用多个线程下载
  • 26. 多线程实现下载一个文件
  • 27. 使用URL ——URL连接 通过URL类提供的方法openConnection(),就可以获得一个URL连接(URLConnection)对象。 public URLConnection openConnection() 通过URL的方法openStream(),只能从网络上读取资源中的数据。通过URLConnection类,可以在应用程序和URL资源之间进行交互,既可以从URL中读取数据,也可以向URL中发送数据。URLConnection类表示了应用程序和URL资源之间的通信连接。 try{ URL url = new URL(“http://sc.ccit.js.cn”); URLConnection uc = url.openConnection(); }catch(MalformedURLException e1){ … }catch(IOException e2){ … }
  • 28. 通过URLConnection对象获取的输入流和输出流,可以与现有的CGI程序进行交互。 URL和URLConnection的区别在于前者代表一个资源的位置,后者代表一种连接。3、使用URL ——URL连接客户端 java程序OutputStreamInputStream CGI程序 STDINSTDOUT 服务器 connectiongetchar()putchar()URL url = new URL("http://sc.ccit.js.cn/~lyw/cgi-bin/test.cgi"); URLConnection uc = url.openConnection(); PrintStream out = new PrintStream(uc.getOutputStream()); BufferedReader in = new BufferedReader( new InputStreamReader( uc.getInputStream() ) ); 示例
  • 29. URLConnection示例public static void main(String args[]) throws Exception { int c; URL hp = new URL("http://news.sina.com.cn/c/2011-04-14/112922291959.shtml"); URLConnection hpCon = hp.openConnection(); long d = hpCon.getDate();System.out.println("Date: " + new Date(d)); System.out.println("Content-Type: " + hpCon.getContentType()); d = hpCon.getExpiration(); System.out.println("Expires: " + new Date(d)); d = hpCon.getLastModified(); System.out.println("Last-Modified: " + new Date(d)); int len = hpCon.getContentLength();System.out.println("Content-Length: " + len); if (len != 0) { InputStream input = hpCon.getInputStream();int i = len; while (((c = input.read()) != -1)) { System.out.print((char) c); } input.close(); } else { System.out.println("No content available."); }}
  • 30. Socket通信在Java中,基于TCP协议实现网络通信的类有两个:在客户端的Socket类和在服务器端的ServerSocket类。 在服务器端通过指定一个用来等待的连接的端口号创建一个 ServerSocket实例。 在客户端通过规定一个主机和端口号创建一个 socket实例,连到服务器上。 ServerSocket类的accept方法使服务器处于阻塞状态,等待用户请求。
  • 31. Socket通信模型
  • 32. (本页无文本内容)
  • 33. Socket/ServerSocket类的构造方法 Socket(InetAddress address, int port); Socket(String host, int port); ServerSocket(int port); ServerSocket(int port, int count); 这些方法都将抛出例外IOException,程序中需要捕获处理 Socket的输入/输出流管理 public InputStream getInputStream() public void shutdownInput() 关闭输入流 public OutputStream getOutputStream() public void shutdownOutput() 关闭输出流 关闭Socket public void close() throws IOException 设置/获取Socket数据 public InetAddress getInetAddress()、public int getPort(),… public void setSoTimeout(int timeout),… 这些方法都将抛出例外SocketException,程序中需要捕获处理。
  • 34. 4. 网络编程的四个基本步骤创建socket; 打开连接到socket的输入/输出流; 按照一定的协议对socket进行读/写操作; 关闭socket;
  • 35. 1、建立Socket 在客户端: try{ Socket client = new Socket(host, 4444); }catch(IOException e){} 在服务器端: try{ ServerSocket server = new ServerSocket(4444); }catch(IOException e){} Socket socket = null; try{ socket = server.accept(); //等待客户端连接 //派发线程处理 }catch(IOException e){}
  • 36. 2、在客户端和服务器端同时打开输入/输出流 类Socket提供了方法getInputStream()和getOutputStream()来得到Socket对应的输入/输出流以进行数据读写操作,它们分别返回InputStream对象和OutputStream对象。 为了便于读写数据,应在返回的输入/输出流对象上建立过滤流,如DataInputStram/DataOutputStram、BufferedInputStream/ BufferedOutputStream、PrintStream;InputStreamReader/ OutputStreamWriter、BufferedReader/ BufferedWriter、PrintWriter等。 BufferedReader = new BufferedReader(new InputStreamReader( socket.getInputStream() ) ); BufferedWriter = new BufferedWriter( new InputStreamWriter( socket.getOutputStream() ) ); 3、关闭输入/输出流和Socket 在客户端和服务器端分别关闭输入/输出流和Socket:先关闭所有相关的输入/输出流,在关闭Socket。
  • 37. 创建服务器(端口号)定义数据成员服务器等待 网络连接建立socket流发送谈话信息接收用户谈话信息创建Socket实例定义数据成员建立socket流发送谈话信息接收服务器谈话信息关闭流accept()127.0.0.1 44444444结束谈话(Bye.)结束谈话(Bye.)关闭流服务器端客户端
  • 38. 简单的client/server程序import java.net.*; import java.io.*; public class TestServer { public static void main(String args[]) { try { ServerSocket s = new ServerSocket(8888); while (true) { Socket s1 = s.accept(); OutputStream os = s1.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); dos.writeUTF("Hello," + s1.getInetAddress() + "port#" +s1.getPort() + " bye-bye!"); dos.close(); s1.close(); } }catch (IOException e) { System.out.println("出错:" + e);} } }
  • 39. 简单的client/server程序import java.net.*; import java.io.*; public class TestClient { public static void main(String args[]) { try { Socket s1 = new Socket("127.0.0.1", 8888); InputStream is = s1.getInputStream(); DataInputStream dis = new DataInputStream(is); System.out.println(dis.readUTF()); dis.close(); s1.close(); } catch (ConnectException connExc) { System.err.println("服务器连接失败!"); } catch (IOException e) { } } }
  • 40. telnet工具的使用1 cmd 模式下输入telnet 2 输入help 3 set ? 查询 4 set localecho
  • 41. 检测端口冲突问题命令netstat –an 通过配置参数来指定Tcp程序的端口。 这样的好处是可以由用户手动指定端口号 如果配置参数没有指定,则使用默认端口 号。
  • 42. 4、Socket通信 ——简单的Client/Server 在本地机器上测试网络程序用回绕地址 Socket socket = new Socket(“127.0.0.1”, 4444); 建立socket连接后,还应该建立输入输出数据流。 要控制好输入/输出流和Socket关闭的时间。 如果网络的一端已经关闭,另一端读到null。 在运行时,服务器端程序一般应先行启动。 示例s 示例c
  • 43. 当用两个telnet客户端同时连接服务器时,只有一个可以通信,前一个退出后,后一个才能通信。这就是我们下一步的任务:多线程服务器实现。
  • 44. 1 服务器端创建一个ServerSocket,调用accept等待客户端连接。 2 客户端创建一个socket并请求和服务器端连接 3 服务器端接受客户端请求,创建一个socket与该客户建立专线连接 4 建立了连接的二个socket在一个单独的线程上对话 5 服务器端继续等待新的连接。
  • 45. 解决方案: 将服务器写成多线程的,不同的处理线程为不同的客户服务。主线程只负责循环等待,处理线程负责网络连接,接收客户输入的信息。 //主线程 while (true) { accept a connection ; create a thread to deal with the client ; }end while 4、Socket通信 ——支持多Client Server client1client2serverthread2serverthread1……
  • 46. 4、Socket通信 ——支持多Client serverSocket = new ServerSocket(4444); while (listening) { Socket socket; socket = serverSocket.accept(); //程序将在此等候客户端的连接 new MultiTalkServerThread(socket, clientNumber).start(); clientNumber++; //记录客户数目 } serverSocket.close();class MultiTalkServerThread extends Thread { public MultiTalkServerThread(Socket socket, int clientNumber) { this.socket = socket; this.clientNumber = clientNumber + 1; } public void run() { … } }
  • 47. 4、Socket通信 ——支持多Client客户1客户2服务器线程1( )线程2( )MultiTalkServer.java
  • 48. 4、Socket通信 ——Client之间通过Server通信 可以在服务器端将与各客户进行通信的Socket和线程管理起来,从而各客户之间可以在服务器端的协助下进行通信。服务器 (4444) accept socket 客 户 2IP1 client1线程1客 户 1IP2 client2线程2
  • 49. 通过Tcp网络传递对象ObjectInputStream ObjectOutputStream 通过ObjectInputStream 和ObjectOutputStream实现聊天。
  • 50. UDP协议是无连接的协议,它以数据报作为数据传输的载体。数据报是一个在网络上发送的独立信息,它的到达、到达时间以及内容本身等都不能得到保证。数据报的大小是受限制的,每个数据报的大小限定在64KB以内。 UDP协议无需在发送方和接收方建立连接,但也可以先建立连接。数据报在网上可以以任何可能的路径传往目的地。 在Java中,基于UDP协议实现网络通信的类有: 用于表达通信数据的数据报类DatagramPacket 用于进行端到端通信的类DatagramSocket5、数据报通信
  • 51. 类DatagramPacket 构造方法 public DatagramPacket(byte[] buf, int length) public DatagramPacket(byte[] buf, int offset, int length):这两个方法用于接收数据 public DatagramPacket(byte[] buf, int length, InetAddress address, int port) public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):这两个方法用于发送数据 获取数据——获取接收报中的信息 public InetAddress getAddress() public byte[] getData() public int getLength() public int getPort() 设置数据——设置发送报中的信息 setAddress(InetAddress iaddr)、setPort(int iport)、setData(byte[] buf)、setData(byte[] buf, int offset, int length) 、setLength(int length)5、数据报通信 ——数据报
  • 52. 类DatagramSocket 构造方法 public DatagramSocket() public DatagramSocket(int port):在指定的端口通信 public DatagramSocket(int port, InetAddress laddr):在指定的地点运行 这三个方法都将抛出例外SocketException,程序中需要捕获处理。 最主要的方法——发送与接收数据报 public void receive(DatagramPacket p) public void send(DatagramPacket p) 这两个方法都将抛出例外IOException,程序中需要捕获处理。 其他方法 public void connect(InetAddress address, int port):与指定的机器通信 public void disconnect():关闭与指定机器的连接 public void close():关闭Socket5、数据报通信 ——点到点通信
  • 53. DatagramSocket datagramSocket; //DatagramPacket是用来接收发送的数据的 DatagramPacket outDataPacket; InetAddress clientAddress=InetAddress.getLocalHost(); byte[] sendcont; datagramSocket = new DatagramSocket(); sendcont="hello".getBytes(); // 搭建一个outDataPacket将当前的时间发往客户端。 outDataPacket = new DatagramPacket(sendcont, sendcont.length, clientAddress, 9999); // 通过一个DatagramPacket将数据发送到客户端,客户端的地址由DatagramPacket //指定 datagramSocket.send(outDataPacket); System.out.println("数据已经成功发送");发送方
  • 54. //DatagramSocket相当于建立一个服务器 DatagramSocket datagramSocket; //DatagramPacket是用来接收发送的数据的 DatagramPacket inDataPacket; // Datagram packet from the client datagramSocket = new DatagramSocket(9999);//要接收就要监听某一个端口 byte[] msg = new byte[100]; inDataPacket = new DatagramPacket(msg, msg.length); // 调用receive方法接收数据到DatagramPacket 中 datagramSocket.receive(inDataPacket); //通过DatagramPacket得到地址和端口 InetAddress clientAddress = inDataPacket.getAddress(); int clientPort = inDataPacket.getPort(); String msgs = new String(msg); System.out.println(msgs); System.out.println(clientAddress); System.out.println(clientPort);接收方
  • 55. 建立数据报socket();建立一个数据报packet等待请求报文建立数据报socket建立一个请求数据报发出请求获得对方地址构成信息包发送出去创建接收包等待接收接收端发送端
  • 56. 5、数据报通信 ——点到点通信示例 12、客户端(接收端)1、服务器端(发送端)示例
  • 57. 5、数据报通信 ——点到点通信发送端发出数据报的标准步骤: 1. 定义数据成员 DatagramSocket socket; DatagramPacket packet; InetAddress address;(用来存放接收方的地址) int port; (用来存放接收方的端口号) 2. 创建数据报Socket对象 try{ socket = new DatagramSocket(4445); }catch(java.net.SocketException e) {} socket 绑定到一个本地的可用端口,等待接收客户的请求。
  • 58. 3.分配并填写数据缓冲区(一个字节类型的数组) byte[] buf = new byte[256]; 存放从客户端接收的请求信息。 4.创建一个DatagramPacket packet = new DatagramPacket(buf, 256); 用来从socket接收数据,它只需要两个参数。 5. 服务器阻塞 socket.receive(packet); 在客户的请求数据报到来之前一直等待。5、数据报通信 ——点到点通信
  • 59. 6. 从到来的包中得到地址和端口号 InetAddress address = packet.getAddress(); int port=packet.getPort(); 7. 将数据送入缓冲区 或来自文件、或键盘输入 8. 建立报文包,用来从socket上发送信息 packet = new DatagramPacket(buf, buf.length, address, port); 9. 发送数据包 socket.send(packet); 10.关闭socket socket.close();5、数据报通信 ——点到点通信
  • 60. 5、数据报通信 ——点到点通信接收端接收数据报的标准步骤: 1. 定义数据成员 int port; InetAddress address; DatagramSocket socket; DatagramPacket packet; byte[] sendBuf = new byte[256]; 2. 建立socket socket = new DatagramSocket();
  • 61. 5、数据报通信 ——点到点通信3. 向服务器发出请求报文 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); 如果没有到就一直等待,因此实用程序要设置时间限度 5. 处理接收到的数据 String received=new String(packet.getData()); System.out.println(received);
  • 62. 每一台机器都有从0~65535个端口号,其中的每一个数字,可供一个程序通信用。通常情况下0~~1024的端口要尽量避免使用——我们称它为“系统预留端口”。例如打开网页时,连接的是服务器上的80端口,因为它是默认的,所以在浏览器地址栏不需要输入这个端口号。端口号
  • 63. 小 结学习了URL类和Socket类 学习了用Socket进行网络编程
  • 64. 课后作业多线程的下载程序,控制台实现。 建立一个server/client程序,要求: 尝试构思编写一个聊天程序,能够进行多人的群聊功能,并且能实现退出功能、登陆功能。
  • 65. 补充Http协议头 Get /index.html HTTP/1.1 Host: 打二个回车