Download presentation
Presentation is loading. Please wait.
1
1、了解TCP和UPD的特点和区别 2、了解TCP的连接传输数据过程 3、能够用TCP建立数据连接和传输数据
2018/11/22 知识点 1、了解TCP和UPD的特点和区别 2、了解TCP的连接传输数据过程 3、能够用TCP建立数据连接和传输数据
2
根据流动方向的不同,流分为输入流和输出流; 对于输入和输出流,由于传输格式的不同,又分为字节流和字符流:
流的类型 根据流动方向的不同,流分为输入流和输出流; 对于输入和输出流,由于传输格式的不同,又分为字节流和字符流: 字节流是指8位的通用字节流,以字节为基本单位,在java.io包中,对于字节流进行操作的类大部分继承于InputStream(输入字节流)类和OutputStream(输出字节流)类; 字符流是指16位的Unicode字符流,以字符(两个字节)为基本单位,非常适合处理字符串和文本,对于字符流进行操作的类大部分继承于Reader(读取流)类和Writer(写入流)类。
3
Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四)
字节流和字符流 Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四) Java中其他多种多样变化的流均是由它们派生出来的
4
节点流类型
5
处理流类型
6
FileInputStream类的构造方法
构 造 方 法 说 明 FileInputStream(File file) throws FileNotFoundException 使用File对象创建文件输入流对象,如果文件打开失败,将抛出异常 FileInputStream(String name) 使用文件名或路径创建文件输入流对象,如果文件打开失败,将抛出异常
7
FileInputStream类的常用方法
方 法 原 型 说 明 int read() throws IOException 读取文件中的数据,一次读取一个字节,读取的数据作为返回值返回,如果读到文件末尾则返回-1,有可能抛异常,必须捕捉 int read(byte[] b) 读取文件中的数据,将读到的数据存放到byte型数组中,并返回读取的字节的数量,未读到数据返回-1,有可能抛异常,必须捕捉 void close() 关闭流对象,有可能抛异常,必须捕捉
8
FileInputStream对象读文件示例1
public class FileInputStreamDemo1 { public static void main(String[] args) { try { File file = new File("test.txt"); //创建文件对象 //使用文件对象创建文件输入流对象,相当于打开文件 FileInputStream fis = new FileInputStream(file); for (int i = 0; i < file.length(); i++) { char ch = (char)(fis.read()); //循环读取字符 System.out.print(ch); } System.out.println(); fis.close(); //关闭流 } catch (FileNotFoundException fnfe) { System.out.println("文件打开失败。"); } catch (IOException ioe) { ioe.printStackTrace();
9
FileInputStream对象读文件示例2
public class FileInputStreamDemo2 { public static void main(String[] args) { try { File file = new File("test.txt"); //创建文件对象 FileInputStream fis = new FileInputStream(file); //根据文件的字节长度创建字节数组 byte[] buf = new byte[(int)(file.length())]; fis.read(buf); //读取文件中的数据存放到字节数组中 String str = new String(buf); //利用字节数组创建字符串 System.out.println(str); //打印字符串 fis.close(); //关闭流 } catch (FileNotFoundException fnfe) { System.out.println("文件打开失败。"); } catch (IOException ioe) { ioe.printStackTrace(); }
10
使用FileOutputStream类写文件
FileOutputStream类称为文件输出流,继承于OutputStream类,是进行文件写操作的最基本类; 它的作用是将内存中的数据输出到文件中,我们可以利用它来写文件。
11
FileOutputStream类的构造方法
构 造 方 法 说 明 FileOutputStream(File file) throws FileNotFoundException 使用File对象创建文件输出流对象,如果文件打开失败,将抛出异常 FileOutputStream(File file, boolean append) 使用File对象创建文件输出流对象,并由参数append指定是否追加文件内容,true为追加,false为不追加,异常情况同上 FileOutputStream(String name) 直接使用文件名或路径创建文件输出流对象,异常情况同上 FileOutputStream(String name, boolean append) 直接使用文件名或路径创建文件输出流对象,并由参数append指定是否追加,异常情况同上
12
FileOutputStream类的常用方法
方 法 原 型 说 明 void write(int b) throws IOException 往文件中写数据,一次写一个字节,有可能抛异常,必须捕捉 void write(byte[] b) 往文件中写数据,将byte数组中的数据全部写入到文件中,有可能抛异常,必须捕捉 void close() 关闭流对象,有可能抛异常,必须捕捉
13
FileOutputStream对象写文件示例1
public class FileOutputStreamDemo1 { //在函数内部不进行异常处理,将异常抛出函数外部 public static void main(String[] args) throws IOException String str = "Hello world!"; File file = new File("test.txt"); //创建文件对象 //通过文件对象创建文件输出流对象 //附加第二个参数true,指定进行文件追加,默认为不追加 FileOutputStream fos = new FileOutputStream(file, true); //逐个将字符写入到文件中 for (int i = 0; i < str.length(); i++) fos.write(str.charAt(i)); } fos.close(); //关闭流
14
FileOutputStream对象写文件示例2
public class FileOutputStreamDemo2 { //在函数内部不进行异常处理,将异常抛出函数外部 public static void main(String[] args) throws Exception String str = "I Love Java"; //通过文件名创建文件输出流对象 FileOutputStream fos = new FileOutputStream("test.txt"); //将字符串转化为字节数组 byte[] buffer = str.getBytes(); //将字节数组中包含的数据一次性写入到文件中 fos.write(buffer); //关闭流 fos.close(); }
15
FileInputStream/FileOutputStream小结
由于采用字节方式进行数据传输,不必考虑数据的格式问题,这两个类对文件操作的效率较高; 可以使用这两个类完成复制文件的操作。
16
复制文件示例 public class CopyFileDemo {
public static void main(String[] args) throws IOException { File srcFile = new File("src.dat"); //源文件对象 File destFile = new File("dest.dat"); //目标文件对象 if (!(destFile.exists())) { //判断目标文件是否存在 destFile.createNewFile(); //如果不存在则创建新文件 } //使用源文件对象创建文件输入流对象 FileInputStream fis = new FileInputStream(srcFile); //使用目标文件对象创建文件输出流对象 FileOutputStream fos = new FileOutputStream(destFile); byte[] buf = new byte[1024]; //创建字节数组,作为临时缓冲 System.out.println("开始复制文件..."); int len = 0; while ((len = fis.read(buf)) != -1) { //循环从文件输入流中读取数据 fos.write(buf, 0, len); //写入到文件输出流中(注意文件多写) System.out.println("文件复制成功!"); fis.close(); //关闭流 fos.close();
17
考虑到Java是跨平台的语言,要经常操作Unicode编码的文件,使用字符流操作文件是有必要的;
FileInputStram类和FileOutputStream类虽然可以高效率地读/写文件,但对于Unicode编码的文件,使用它们有可能出现乱码; 考虑到Java是跨平台的语言,要经常操作Unicode编码的文件,使用字符流操作文件是有必要的; 使用字符流将涉及到以下4个类: FileReader类和FileWriter类; BufferedReader类和BufferedWriter类。
18
FileReader类称为文件读取流,允许以字符流的形式对文件进行读操作,其构造方法有3种重载方式,以下是常用的几种:
该类将从文件中逐个地读取字符,效率比较低下,因此一般将该类对象包装到缓冲流中进行操作。 构 造 方 法 说 明 FileReader(File file) throws FileNotFoundException 使用File对象创建文件读取流对象,如果文件打开失败,将抛出异常 FileReader(String name) 使用文件名或路径创建文件读取流对象,如果文件打开失败,将抛出异常
19
BufferedReader类主要为字符流提供缓冲,以提高效率,其构造方法有2种重载方式,以下是常用的几种:
构 造 方 法 说 明 BufferedReader(Reader in) 将字符读取流对象包装成缓冲读取流对象 方 法 原 型 说 明 String readLine() throws IOException 从缓冲读取流中读取一行字符,以字符串的形式返回,有可能抛异常,必须捕捉 void close() 关闭流对象,有可能抛异常,必须捕捉
20
FileReader配合BufferedReader读文件示例
public class RraderDemo { public static void main(String[] args) throws IOException File file = new File("test.txt"); //通过文件对象创建文件读取流对象 FileReader fr = new FileReader(file); //将文件读取流包装成缓冲读取流 BufferedReader br = new BufferedReader(fr); String str; while ((str = br.readLine()) != null) //逐行读取数据 System.out.println(str); } br.close(); //关闭流 fr.close(); //关闭流
21
FileWriter类称为文件写入流,以字符流的形式对文件进行写操作,其构造方法有5种重载,以下是常用的几种:
与FileReader类相似,FileWriter类同样需要使用缓冲流进行包装。 构 造 方 法 说 明 FileWriter(File file) throws IOException 使用File对象创建文件写入流对象,如果文件打开失败,将抛出异常,必须捕捉 FileWriter(File file, boolean append) 使用File对象创建文件写入流对象,并由参数append指定是否追加,异常情况同上 FileWriter(String name) 直接使用文件名或路径创建文件写入流对象,异常情况同上 FileWriter(String name, boolean append) 直接使用文件名或路径创建文件写入流对象,并由参数append指定是否追加,异常情况同上
22
BufferedWriter类可以为FileWriter类提供缓冲,其构造方法有2种重载方式,以下是常用的几种:
构 造 方 法 说 明 BufferedWriter(Writer out) 将字符写入流对象包装成缓冲写入流对象 方 法 原 型 说 明 void write(String str) throws IOException 将一行字符串写入到缓冲写入流中,有可能抛异常,必须捕捉 void newLine() 将一个回车换行符写入到文件中,从而达到换行的效果,有可能抛异常,必须捕捉
23
FileWriter配合BufferedWriter写文件示例
public class WriterDemo { public static void main(String[] args) throws IOException File file = new File("test.txt"); //通过文件对象创建文件输出字符流对象 FileWriter fw = new FileWriter(file); //将文件输出字符流包装成缓冲流 BufferedWriter bw = new BufferedWriter(fw); bw.write("大家好!"); bw.write("我正在学习Java。"); bw.newLine(); //换个新行 bw.write("请多多指教。"); bw.newLine(); //换新行 bw.close(); //关闭流 fw.close(); //关闭流 }
24
System.in的read方法可以从控制台接受输入;
但由于in实际上是一个InputStream类的对象,它只能以字节形式接收数据,并且一次只能接受一个字节,这使输入操作很不便; 必须将System.in进行处理,才可以顺利地从控制台接受输入,这将使用到: InputStreamReader类 BufferedReader类
25
InputStreamReader类用于将InputStream类型的字节输入流对象转换成Reader类型的字符读取流对象;
转换和包装System.in InputStreamReader类用于将InputStream类型的字节输入流对象转换成Reader类型的字符读取流对象; 其构造方法有4种重载方式,常用的如下: 可以使用它来转换System.in,如: InputStreamReader isr = new InputStreamReader(System.in); 这样的字符流效率很低,再使用BufferedReader类来为其建立缓冲,如: BufferedReader br = new BufferedReader(isr); 这样,就可以从控制台接受输入了。 构 造 方 法 说 明 InputStreamReader(InputStream in) 将InputStream对象转换成Reader对象
26
从控制台接受输入示例 public class ConsoleInputDemo {
public static void main(String[] args) throws IOException //将System.in转化成字符流对象 InputStreamReader isr = new InputStreamReader(System.in); //用缓冲流进行包装 BufferedReader br = new BufferedReader(isr); System.out.println("请输入您的姓名:"); String name = br.readLine(); //接受输入 System.out.println("请输入您的年龄:"); int age = Integer.parseInt(br.readLine()); //接受输入 System.out.println("您的姓名:" + name); System.out.println("您的年龄:" + age); br.close(); //关闭流 isr.close(); //关闭流 }
27
从控制台输入并写入到文件示例 /*本例从控制台接受输入,然后写入到文件中,直到用户输入"!!!"为止*/
File file = new File("input.txt"); //创建文件对象 if (!file.exists()) //判断该文件是否存在,如果不存在则创建新文件 { file.createNewFile(); } FileWriter fr = new FileWriter(file); //针对文件对象创建文件写入流对象 BufferedWriter bw = new BufferedWriter(fr); //为文件写入流建立缓冲流 //将控制台输入对象转化成字符流,并建立缓冲流 BufferedReader bin = new BufferedReader(new InputStreamReader(System.in)); String str = bin.readLine(); //接受从控制台输入的一行字符串 while (!(str.equals("!!!"))) //如果输入"!!!"则代表输入结束 bw.write(str); //将从控制台输入的字符串写入到文件中 bw.newLine(); //换新行 str = bin.readLine(); //再从控制台接受输入 //关闭所有已经打开的流 bw.close(); fr.close(); bin.close();
28
FileInputStream和FileOutputStream在读写文件时不考虑数据的类型;
基本数据类型的读/写 FileInputStream和FileOutputStream在读写文件时不考虑数据的类型; FileWriter和FileReader在读写文件时,将所有的数据都看做字符; 但有时候,我们需要将各种类型的数据写入文件或是从文件中读取,DataInputStream类和DataOutputStream类可以满足需要。
29
DataInputStream类可以输入任何类型的数据,但它不可以单独使用,需要要配合其它字节输入流一起使用;
如: //将文件输入流包装成数据输入流,以便从文件中读取各种类型的数据 FileInputStream fis = new FileInputStream("data.dat"); DataInputStream dis = new DataInputStream(fis); 构 造 方 法 说 明 DataInputStream(InputStream in) 利用其它的字节输入流创建数据输入流对象
30
DataInputStream类的常用方法
方 法 原 型 说 明 final boolean readBoolean() throws IOException 从数据输入流中读取一个boolean型数据 final char readChar() 从数据输入流中读取一个char型数据 final int readInt() 从数据输入流中读取一个int型数据 final long readLong() 从数据输入流中读取一个long型数据 final float readFloat() 从数据输入流中读取一个float型数据 final float readDouble() 从数据输入流中读取一个double型数据
31
DataOutputStream类可以输出任何类型的数据,同样也需要配合其他字节输出流一起使用;
如: //将文件输出流包装成数据输出流,以便往文件中写入各种类型的数据 FileOutputStream fos = new FileOutputStream("data.dat"); DataOutputStream dos = new DataOutputStream(fos); 构 造 方 法 说 明 DataOutputStream(OutputStream out) 利用其它的字节输出流创建数据输出流对象
32
DataOutputStream类的常用方法
方 法 原 型 说 明 final void writeBoolean(boolean v) throws IOException 往数据输出流中写入一个boolean型数据 final void writeChar(char v) 往数据输出流中写入一个char型数据 final void writeInt(int v) 往数据输出流中写入一个int型数据 final void writeLong(long v) 往数据输出流中写入一个long型数据 final void writeFloat(float v) 往数据输出流中写入一个float型数据 final void writeDouble(double v) 往数据输出流中写入一个double型数据
33
对象的序列化 对象的序列化是指把对象写到一个输出流中,对象的反序列化是指从一个输入流中读取一个对象 java语言要求只有实现了java.io.Serializable接口的类的对象才能被序列化和反序列化 实现序列化用ObjectOutputStream类 反序列化用ObjectInputStream类
34
ObjectOutputStream ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream("d:/emp.obj")); Employee emp = new Employee("aa", 23); oout.writeObject(emp); oout.close(); ObjectInputStream oin = new ObjectInputStream(new FileInputStream("d:/emp.obj")); Employee e = (Employee) oin.readObject(); System.out.println(e.getName()); System.out.println(e.getAge());
35
java.io包是Java内置的包,其中包含一系列对输入/输出进行操作的类;
总结1 java.io包是Java内置的包,其中包含一系列对输入/输出进行操作的类; File类的对象可以访问文件(或目录)的属性,但不可以进行读/写操作; 从方向上讲,流分为输入流和输出流,但从格式上区分的话,流分为字节流和字符流; 使用FileInputStream类和FileOutputStream类以字节流方式对文件进行读/写操作,这是操作文件最基本的两个类;
36
从控制台接受输入要使用到InputStreamReader类和BufferedReader类;
总结2 FileReader类和FileWriter类配合BufferedReader类和BufferedWriter类可以以字符流方式对文件进行读/写操作; 从控制台接受输入要使用到InputStreamReader类和BufferedReader类; DataInputStream类和DataOutputStream类允许读/写各种基本数据类型; 绝大部分的IO操作都可能抛出IOException。
37
2018/11/22 Java语言程序设计-网络编程 教师:段鹏飞
38
主要内容 使用URL类访问网络资源 基于Socket的客户和服务器编程 基于Datagram客户和服务器编程
39
11.1 URL类编程 URL(Uniform Resource Locator)是统一资源定位器的简写。它表示Internet上某一资源的地址,这些资源包括Web页、文本文件、图形(像)文件和声频片段等。通过URL可以访问Internet和WWW。浏览器通过解析给定的URL可以在网络上查找相应的文件或资源。
40
URL的组成和URL类
41
URL myURL = new URL(“http://www.whut.edu.cn”);
import java.net.* Java将URL封装成URL类,通过构造方法可以实例化一个URL对象。 public URL(String spec) public URL( URL url, String file) public URL(String protocol, String host, String file) public URL(String protocol, String host, int port, String file) URL myURL = new URL(“ URL mydoc = new URL(myURL, “index.html”); URL myURL = new URL(“http”, “ “index.html”); URL myURL = new URL(“http”, “ 80,“index.html”);
42
MalformedURLException
try{ …… URL myURL = new URL(“……”); }catch(Exception e){ //异常处理 }
43
URL类的成员方法 public final Obect getContent(); public String getFile(); public String getHost(); public int getPort(); public String getProtocol(); public String toExternalForm(); public String toString(); public final InputStream openStream() throws ……; public URLConnection openConnection(); ……
44
例1 获取URL对象属性 the Protocol: http the hostname: www.webmeteor.cn
the port: -1 the file: /index.htm the ext:
45
使用URL类读取WWW信息 通过openStream()与指定的URL建立连接并返回一个InputStream类的对象,然后从这一连接中读取数据。 常用的读取网络资源数据的步骤如下: 创建URL类的实例对象; 通过URL类的实例对象的openStream方法建立连接; 读取数据; 关闭数据流;
46
例2 用url.openStream()方法读取WWW数据
47
使用URLConnection连接WWW
URLConnection的对象表示Java程序与URL在网络上的通信连接。 使用URLConnection对象获取WWW资源的步骤: 创建一个URL对象; 调用URL对象的getConnection()方法获得对应的URLConnection对象; 获取输入流并读数据; 关闭连接;
48
例3 使用URLConnection连接服务器
例3 使用URLConnection连接服务器 import java.net. *; import java.io. *; public class urlcon{ public static void main(String args[]){ InputStream is; OutputStream os; int b; try{ URL url=new URL(" URLConnection uric= url.openConnection(); System.out.println("the length:"+uric.getContentLength()); System.out.println("the type:"+uric.getContentType()); System.out.println("the date: "+uric.getDate()); System.out.println("the lastmodified:"+uric.getLastModified()); os=new FileOutputStream("d:\\down.html" ); if(uric.getContentLength()>=1){ is=uric.getInputStream(); while((b=is.read())!= -1){ os.write(b); System.out.write(b); } }else{ System.out.println("no content"); }catch(Exception e){ System.out.println(e);
49
Socket通信 预备知识 Socket是网络上的两个程序通过一个双向的通信连接实现数据交换的通道。或者说网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket,可以说Socket是面向客户/服务器模型设计的。Socket通信机制提供了两种通讯方式:有联接(TCP)和无联接(UDP)方式,分别面向不同的应用需求。 TCP是以连接为基础的流式协议,通信前,首先要建立连接,然后才能通信。因此,能保证同步、准确地进行通信。如果应用程序需要可靠的点对点通信,一般采用TCP这种协议。比如:HTTP,ftp,telnet等应用程序,确保其可靠性对于程序运行是非常关键的。
50
Socket通信 UDP是一种无连接的协议,其系统开销比无联接方式小,但通信链路提供了不可靠的数据报服务,每个数据报都是一个独立的信息,不能保证信源所传输的数据一定能够到达信宿。在该方式下,通信双方不必创建一个联接过程和建立一条通讯链路,网络通信操作在不同的主机和进程之间转发进行。 端口: 数据通过网络到达一台主机(或准确的说是主机的网卡)是通过IP地址实现的。但当该主机运行多个程序时如何识别数据是属于哪个程序的呢? 这就是端口。一个端口只能绑定一个应用程序。通过TCP/UDP通信的应用程序必须知道对方的IP地址和端口号才能通信。端口号可取从0-65535,其中,0-1023为保留端口,提供给众所周知的一些服务。
51
Socket通信的一般过程 使用Socket进行客户/服务器通信程序设计的一般过程是这样的: Server端listen(监听)某个端口是否有连接请求, Client端向Server端发出connect(连接)请求, Server端向Client端发回Accept(接受)消息。 一个连接就建立好了,之后客户端、服务器端都可以用send()、write()等方法与对方通信。
52
Socket通信的一般过程 对于一个功能齐全的Socket的工作过程包含以下四个基本步骤: 创建Socket; 打开连接到Socket的输入输出流; 按照一定的协议对Socket进行读/写操作; 关闭Socket。
53
创建Socket 创建客户端Socket可以通过Socket的构造方法,介绍如下:
public Socket(String host,int port) public Socket(InetAddress address,int port) // 用该方法创建一个与指定远程主机及其端口建立连接; public Socket(String host,Int port,boolean stream) // stream指明Socket是流式Socket还是数据报式Socket public socket(InetAddress address,Int port,boolean stream) Serversocket的构造方法为: public Serversocket(int port) //指定端口号来创建Serversocket对象,该端口为端主机的端口; public Serversocket(int port,int count) //用指定的端口号创建Serversocket对象,如果该端的端口正在使用,只等待count毫秒。
54
打开输入/输出流 public Inputstream getInputstream( ) //得到 Socket建立的输入流
pubic Outputstream getoutputstream( ) //得到 Socket建立的输出流 Socket对象的其他方法: public void close() public InetAddress getlnetAddress() //得到远程主机 IP地址的 InetAddress对象 public int getLocalPort() //得到与远程机连接的本地机的端口号
55
Serversocket对象的其他方法 public Socket accept() //获取与客户端连接的 Socket对象
//accept()为一个阻塞性方法,即该方法被调用后,将等待客户的请求,直到有一个客户启动并请求连接到相同的端口,然后accept()返回一个对应于客户的Socket。 public void close() public InetAddrss getInetAddress() // 得到与客户端相连的 InetAddress对象 public int getLocalPort() // 得到服务器在监听的端口号
56
java.net.Socket类 Socket应用 表示TCP连接的客户方(Client),和谁连接 Socket对象包括两个流 操作步骤
指定对方的IP地址和端口号 public Socket(String host, int port) throws UnknownHostException, IOException Socket对象包括两个流 Socket代表了TCP所定义的双向通信连接的一个端点 输入流(读取通过网络进来的数据) public InputStream getInputStream() throws IOException 输出流(将数据写入输出流中,并通过网络发送) public OutputStream getOutputStream() throws IOException 操作步骤 先建立连接 进行流的读写操作
57
对客户端对Socket进行读写-实例 客户端 服务器端 Socket应用 Localhost Socket OutputStream
InputStream me.whut.edu.cn ServerSocket InputStream OutputStream 客户端 服务器端
58
对客户端对Socket进行读写-实例 Socket应用 me.whut.edu.cn ServerSocket Localhost
OutputStream InputStream Socket应用 对客户端对Socket进行读写-实例 import java.net.*; import java.io.*; public class SimpleClient { public static void main(String args[]) { Socket s = new Socket(“me.whut.edu.cn”, 5432); InputStream in = s.getInputStream(); DataInputStream dis = new DataInputStream(in); String st = dis.readUTF(); System.out.println(st); in.close(); s.close(); } 建立连接 打开输入流 读取输入流 关闭输入流 关闭连接
59
java.net.ServerSocket类
TCP连接的服务器方(Server),监听端口 等待自客户端发来的连接 public ServerSocket(int port) throws IOException 接收连接请求 public Socket accept() throws IOException Listens for a connection to be made to this socket and accepts it. The method blocks(阻塞) until a connection is made 服务器端通过所接收到的Socket对象和客户端通信 Socket代表了TCP所定义的双向通信连接的一个端点 操作步骤 监听端口 接收连接 进行流的读写操作
60
对ServerSocket的实现-实例 客户端 服务器端 Socket应用 me.whut.edu.cn ServerSocket
Localhost Socket OutputStream InputStream 客户端 服务器端
61
Socket应用 me.whut.edu.cn ServerSocket Localhost Socket OutputStream
InputStream Socket应用 ServerSocket s = null; String hello = “Hello World!”; try { s = new ServerSocket(5432); } catch(IOException e) { System.out.println(e); System.exit(1); } while(true) { Socket cs = s.accept(); OutputStream out = cs.getOutputStream(); DataOutputStream dos = new DataOutputStream(out); dos.writeUTF(hello); out.close(); cs.close(); } catch(IOException e) { System.out.println(e); } 监听端口 接收连接 打开输出流 写入输出流 关闭输出流 关闭连接
62
Socket应用 客户端与服务器端的实现 服务器端 客户端
63
多线程的服务器实现 Socket应用 为每个客户的连接(Socket)分配一个线程,让其独立处理 两种实现方式
作为java.lang.Thread类的子类 实现java.lang.Runnable接口 Client 1 Socket Port 7 me.whut.edu.cn ServerSocket 1 3 2 1 Thread 1 2 Client n Socket 3 Thread n
64
多线程的服务器实现-实例 Socket应用 ServerSocket s = new ServerSocket(5432);
boolean listening = true; while (listening) new ServerThread(s.accept()).start(); s.close(); class ServerThread extends Thread { … … public void run() { }
65
数据报通信 数据报(Datagram)使网络层数据单元在介质上传输信息的一种逻辑分组格式,它是一种在网络中传播的、独立的、自身包含地址信息的消息,它能否到达目的地,到达的时间,到达时内容是否会变化不能准确知道的。它的通讯双方是不需要建立连接的,对于一些不需要很高质量的应用程序来说,数据报通讯是一个非常好的选择。 在Java的java.net包中有两个类DatagramSocket和DatagramPacket用来支持数据报通信。
66
DatagramSocket的构造方法 public DatagramSocket()
//构造一个数据报socket,并使其与本地主机任一可用的端口连接。若打不开socket则抛出SocketException异常。 public DatagramSocket(int port) //构造一个数据报socket,并使其与本地主机指定的端口连接。若打不开socket或socket无法与指定的端口连接则抛出SocketException异常。
67
DatagramPacket的构造方法 DatagramPacket( byte bufferedarray[ ], int offset, int length, InetAddress address, int port) //构造一个包长度为length的包传送到指定主机指定端口号上的数据报文包,参数length必须小于等于bufferedarry.length DatagramPacket( byte bufferedarray[ ], int length) //接收从服务器返回的结果数据报文 ,只需指明存放接收的数据报的缓冲区和长度。
68
客户端与服务器之间数据报通讯的方法 客户端应用程序的工作流程
建立数据报通讯的Socket,我们可以通过创建一个DatagramSocket对象来实现它。 创建一个数据报文包,用来实现无连接的包传送服务。每个数据报文包是用DatagramPacket类来创建,DatagramPacket对象封装了数据报包数据,包长度,目标地址,目标端口。作为客户端要发送数据报文包,要调用DatagramPacket类的构造方法创建DatagramPacket对象,将要发送的数据和包文目的地址等信息放入对象之中。
69
客户端与服务器之间数据报通讯的方法 创建完DatagramSocket和DatagramPacket对象,就可以发送数据报文包了。发送是通过调用DatagramSocket对象的send方法实现,它需要以DatagramPacket对象为参数,将刚才封装进DatagramPacket对象中的数据组成数据报发出。 也可以接收数据报文,为了接收从服务器返回的结果数据报文,需要创建一个新的DatagramPacket对象,调用DatagramSocket对象的receive()方法来完成接收数据报的工作,此时需要将上面创建的DatagramPacket对象作为参数,该方法会一直阻塞知道收到一个数据报文包,此时DatagramPacket的缓冲区中包含的就是接收到的数据,数据报文包中也包含发送者的IP地址,发送者机器上的端口号等信息。
70
客户端与服务器之间数据报通讯的方法 建立数据报通讯的Socket,我们可以通过创建一个DatagramSocket对象来实现它。
处理接收缓冲区内的数据,获取服务结果。 当通讯完成后,可以使用DatagramSocket对象的close()方法来关闭数据报通讯Socket。当然,Java自己会自动关闭Socket,释放DatagramSocket和DatagramPacket所占用的资源。但是作为一种良好的编程习惯,还是要显示的予以关闭。
71
服务器端应用程序的工作流程 不同于基于数据流通讯方式,在数据报通讯中,通讯双方之间并不要建立连接,所以,服务器应用程序通讯过程与客户端应用程序的通讯过程使非常相似的,也要建立数据报通讯DatagramSocket,构建数据报文包DatagramPacket,接收数据报和发送数据报,处理接收缓冲区内的数据,通讯完毕后,关闭数据报通讯Socket。不同的是,服务器应用程序要面向网络中的所有计算机,所以服务器应用程序收到一个包文后要分析它,得到数据报的源地址信息,这样才能创建正确的返回结果报文给客户机。
72
2018/11/22 谢谢
Similar presentations