1、(是否存在面向连接的数据包socket?)因此数据包 socket 是基于 UDP 的不可靠 IPC。Java 为数据包 socket API 提供两个类:(1)针对 socket 的 datagramSocket 类(2)针对数据包交换的 datagramPacket 类希望使用该 API 发送和接收数据的进程须实例化一个 datagramSocket 对象,每个 socekt被绑定到该进程所在及其的某个 UDP 端口上。为了向其他进程发送数据包,进程必须创建一个代表数据包本身的对象。该对象通过实例化一个 datagram socket 对象创建。在接收者进程中,datagramPacket
2、 对象也必须被实例化并绑定到一个本地端口上,该端口必须与发送者数据包的定义一致。接收进程创建一个指向字节数组的 DatagramPacket,并调用 datagramSocket 对象的 receive 方法,将 DatagramPacket 对象指针作为参数定义。2. 并行编程(以 Java 为例 1 )一个线程是比进程更小的执行粒度。 Java 虚拟机允许应用程序有多个执行线程同时运行。有两种方法来创建一个新线程的执行。一个是声明一个类是一个线程的子类。这个子类应重写 Thread 类的 run 方法。一个子类的实例可以被分配和启动。另一种方法创建一个线程,并同时声明一个类实现了 Runn
3、able 接口(这个类要实现 run 方法)。一个类的实例可以被分配并作为参数传递给创建的线程,并启动线程。例如:u 创建一个类是 Thread 的子类:class SomeThread extends Thread SomeThread() public void run() . . .SomeThread p = new SomeThread();p.start();u 创建一个实现 Runnable 接口的类并传递给线程:class SomeRun implements Runnable SomeRun() SomeRun p = new SomeRun(143);new Thread(
4、p).start();当一个实现 Runnable 接口的类被执行时,可以没有子类。实例化一个 Thread 实例,并通过自身作为目标线程。在大多数情况下,如果你只打算重写的 run()方法,并没有其它的线程方法,应使用 Runnable 接口。因为类不应该被继承,除非程序员有意修改或增强类的基本行为。五、实验内容1. 构建客户端程序(1) 构建 datagramSocket 对象实例(2) 构建 DatagramPacket 对象实例,并包含接收者主机地址、接收端口号等信息(3) 调用 datagramSocket 对象实例的 send 方法,将 DatagramPacket 对象实例作为参
5、数发送。2. 构建服务器端程序(1) 构建 datagramSocket 对象实例,指定接收的端口号。(2) 构建 DatagramPacket 对象实例,用于重组接收到的消息。(3) 调用 datagramSocket 对象实例大家 receive 方法,进行消息接收,并将DatagramPacket 对象实例作为参数。六、实验报告1. 客户端和服务器端程序的伪代码;客户端:import java.io.IOException;import .DatagramPacket;import .DatagramSocket;import .InetAddress;import java.util.
6、Scanner;public class Client public static void main(String args) throws IOException / 创建一个客户端DatagramSocket,使用随机端口 DatagramSocket socket = new DatagramSocket(); / 初始化发送用的DatagramSocket,它包含一个长度为0的字节数组 DatagramPacket outPacket = new DatagramPacket(new byte0 , 0 , InetAddress.getByName(127.0.0.1) , 300
7、00); / 定义接收网络数据的字节数组 byte inBuff = new byte4096; DatagramPacket inPacket =new DatagramPacket(inBuff , inBuff.length); / 创建键盘输入流 Scanner scan = new Scanner(System.in); / 不断地读取键盘输入 while(scan.hasNextLine() / 将键盘输入的一行字符串转换成字节数组 byte buff = scan.nextLine().getBytes(); / 设置发送用的DatagramPacket中的字节数据 outPac
8、ket.setData(buff); / 发送数据报 socket.send(outPacket); / 读取Socket中的数据,读到的数据放在inPacket所封装的字节数组中 socket.receive(inPacket); System.out.println(new String(inBuff , 0 , inPacket.getLength(); 服务端:public class Services / 定义接收网络数据的字节数组 byte inBuff = new byte4096; / 创建DatagramSocket对象 DatagramSocket socket = new
9、 DatagramSocket(30000); / 以指定字节数组创建准备接收数据的DatagramPacket对象 DatagramPacket inPacket = new DatagramPacket(inBuff , inBuff.length); String message=消息已经收到!; while(true) socket.receive(inPacket); / 将接收到的内容转换成字符串后输出 System.out.println(new String(inBuff, 0 , inPacket.getLength(); / 从字符串数组中取出一个元素作为发送数据 byte
10、 sendData = message.getBytes(); / 以指定的字节数组作为发送数据,以刚接收到的DatagramPacket的 / 源SocketAddress作为目标SocketAddress创建DatagramPacket / 定义一个用于发送的DatagramPacket对象 DatagramPacket outPacket= new DatagramPacket(sendData , sendData.length , inPacket.getSocketAddress(); / 发送数据 2. 试验过程中的问题和解决途径;问题:对于DatagramPacket、Data
11、gramSocket不怎么了解解决途径:查阅JDK api文档3. 实验结果:客户端1:客户端2:七、思考题1. 如何避免数据包丢失而造成的无限等待问题?答:我认为可在发包时设定一个定时器,若发出去的包在一定时间内没有收到答应,则再发一次。为了避免接受者接到重复的包,可以给数据包加个序号,接受者收包时查看序号即可。2. 如何实现全双工的数据包通信?利用端口套接字之间的通信功能。实验二 流式 socket 应用1. 理解流式 socket 的原理2. 实现流式 socket 通信1. 预习实验指导书及教材的有关内容,了解流式 socket 的通信原理;2. 熟悉 java 环境和程序开发过程;3
12、. 尽可能独立思考并完成实验。a) 独立计算机;b) Windows 操作系统;Socket API 是一种作为 IPC 提供低层抽象的机制。尽管应用人员很少需要在该层编写代码,但理解 socket API 非常重要,因为:1,高层设施是构建于 socket API 之上的,即他们是利用 socket API 提供的操作来实现;2,对于以响应时间要求较高或运行于有限资源平台上的应用来说,socket API 可能是最适合的。在 Internet 网络协议体系结构中,传输层上有 UDP 和 TCP 两种主要协议,UDP 允许使用无连接通信传送,被传输报文称为数据包。而 TCP 则允许面向连接的可
13、靠通信,这种 IPC称为流式 socket。Java 为流式 socket API 提供两类 socket(1)式用于连接的连接 socket(2)式用于数据交换的数据 socket。1. 构建客户端程序和服务器端程序都需要的 MystreamSocket 类,定义继承自 java Socket的 sendMessage 和 receiveMessage 方法2. 构建客户端程序(1) 创建一个 MyStreamsocket 的实例对象,并将其指定接收服务器和端口号(2) 调用该 socket 的 receiveMessage 方法读取从服务器端获得的消息3. 构建服务器端程序(1) 构建连接
14、 socket 实例,并与指定的端口号绑定,该连接 socket 随时侦听客户端的连接请求(2) 创建一个 MyStreamsocket 的实例对象(3) 调用 MyStreamsocket 的实例对象的 sendMessage 方法,进行消息反馈。1. 应用程序的结构图,说明程序之间的关系;2. 程序的伪代码。公用服务功能MystreamSocket.java:import .*;import java.io.*;public class MystreamSocket extends Socket private Socket socket; private BufferedReader i
15、nput; private PrintWriter output; /客户端的构造方法 MystreamSocket(InetAddress acceptorHost, int acceptorPort ) throws SocketException, IOException socket = new Socket(acceptorHost, acceptorPort ); setStreams(); /服务端的构造方法 MystreamSocket(Socket socket) throws IOException this.socket = socket; /设置输出输入流 privat
16、e void setStreams() throws IOException InputStream inStream = socket.getInputStream(); input = new BufferedReader(new InputStreamReader(inStream); OutputStream outStream = socket.getOutputStream(); output = new PrintWriter(new OutputStreamWriter(outStream); /发送消息 public void sendMessage(String messa
17、ge) throws IOException output.println(message); output.flush(); /接收消息 public String receiveMessage() throws IOException String message = input.readLine(); return message; /关闭所有打开的东西 public void closeAll() try if(input!=null) input.close(); if(output!=null) output.close(); if(socket!=null) socket.clo
18、se(); catch (IOException e) / TODO 自动生成的 catch 块 e.printStackTrace();客户端Client .java:public class Client public static void main(String args) try InetAddress hostname=InetAddress.getByName(localhost); MystreamSocket mss=new MystreamSocket(hostname,12345); mss.sendMessage(我是客户端,我请求连接! System.out.prin
19、tln(mss.receiveMessage(); mss.close(); catch (IOException e) / TODO 自动生成的 catch 块 e.printStackTrace(); 服务端Services.java:import .ServerSocket;import .Socket;public class Services ServerSocket services=new ServerSocket(12345); Socket socket; while(true) /监听端口看是否有连接请求 socket=services.accept(); /多线程处理连接
20、请求 new ServicesThread(socket).start(); 服务端多线程实现ServicesThread.java:public class ServicesThread extends Thread Socket socket; ServicesThread(Socket socket) this.socket=socket; public void run() MystreamSocket mss=new MystreamSocket(socket);消息已收到! mss.closeAll();1. 如何实现全双工的流式 socket 通信?服务端监听端口,每当有一个连接
21、请求发来时,就与其建立新的连接,然后利用其提供的功能进行通信。2. 如何实现安全 socket API?注意在通信过程中的各种异常情况的捕获与处理。3. 如何实现 1 对多的并发?在服务端使用多线程。实验三 客户/ 服务器应用开发1. 验证 daytime 和 echo 程序,2. 实现包 socket 支撑的 C/S 模式 IPC 机制3. 实现流式 socket 支撑的 C/S 模式 IPC 机制1. 预习实验指导书及教材的有关内容,了解 daytime 和 echo 要提供的具体服务内容;2. 复习包 socket 和流式 socket 的实现原理;3. 实验前认真听讲,服从安排。尽可能
22、独立思考并完成实验。C/S 模式是主要的分布式应用范型,其设计的目的是提供网络服务。网络服务指如daytime、telnet、ftp 和 WWW 之类的允许网络用户共享资源的服务。要构建 C/S 范型的应用就必须解决以下一些关键问题:(1) 如何通过会话实现多个用户的并发问题(2) 如何定义客户和服务器在服务会话期间必须遵守的协议(3) 服务定位问题(4) 进程间通信和事件同步问题:语法、语义和响应(5) 数据表示问题在解决了这些问题的基础上,C/S 范型必须遵从 3 层结构的软件体系结构:(1) 表示层,提供与客户端进行交互的界面(2) 应用逻辑层,定义服务器和客户端要处理的主要事务的业务逻
23、辑(3) 服务层,定义应用逻辑层所需要的底层支持技术,例如定义其 IPC 机制里的receive 方法和 send 方法等。1. 构建用数据包 socket 实现的 daytime 客户端程序(1) 构建表示层程序 DaytimeClient1.java(2) 构建应用逻辑层程序 DaytimeHelper1.java(3) 构建服务层程序 MyClientDatagramSocket.java2. 构建用数据包 socket 实现的 daytime 服务器端程序(1) 构建表示层和应用逻辑层程序 DaytimeServer1.java(2) 构建服务层程序 MyServerDatagramS
24、ocket.java(3) 构 建 服 务 层 程 序 MyServerDatagramSocket.java 所 需 要 的 下 层 程 序DatagramMessage.java(它封装了客户端的消息和地址)3. 构建用流式 socket 实现的 daytime 应用程序包4. 构建用数据包 socket 实现的 echo 应用程序包5. 构建用流式 socket 实现的 echo 应用程序包1. 用数据包 socket 实现的 daytime 应用程序包的构架,列明各程序之间的关系;代码:DaytimeClient1.javapublic class DaytimeClient1 public static void main(String args) InputStreamReader is = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(is);try System.out.println(Welcome to the Daytime client.n +What is the name of the server host
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1