TCP/UDP(大作业)
文章目录
Java 网络编程
首先理清一个概念:网络编程不等于网站编程,网络编程即使用套接字来达到进程间通信,现在一般称为TCP/IP编程。
一、什么是计算机网络?
(一)概念
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
(二)计算机网络的主要功能
1、资源共享*
2、信息传输与集中处理*
3、均衡负荷与分布处理
4、综合信息服务(www / 综合业务数字网络 ISDN)
(三)计算机网络三高问题
高并发,高性能,高可用。
(四)计算机网络分类
局域网
城域网
广域网
互联网
(Local Area Network;LAN) 通常我们常见的“LAN”就是指局域网,这是我们最常见、应用最广的一种网络
二、网络通信协议及接口
(一)什么是网络通信协议?
通过计算机网络可以实现不同计算机之间的连接与通信,但是计算机网络中实现通信必须有一些约定即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
国际标准化组织(ISO,即International Organization for Standardization)定义了网络通信协议的基本框架,被称为OSI(Open System Interconnect,即开放系统互联)模型。OSI模型制定的七层标准模型,分别是:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层。
虽然国际标准化组织制定了这样一个网络通信协议的模型,但是实际上互联网通讯使用最多的网络通信协议是TCP/IP网络通信协议
TCP/IP 是一个协议族,也是按照层次划分,共四层:应用层,传输层,互连网络层,网络接口层(物理+数据链路层)。
(二)什么是网络通信接口?
为了使两个节点之间能进行对话,必须在他们之间建立通信工具(即接口),使彼此之间,能进行信息交换。接口包括两部分:
硬件装置:实现结点之间的信息传送
软件装置:规定双方进行通信的约定协议
(三)通信协议分层思想
1.为什么要分层?
由于网络结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式是层次方式,即同层间可以通信、上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。
2.通信协议的分层规定
把用户应用程序作为最高层,把物理通信线路作为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准。
3.参考模型
上图中,TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能。
- 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。
- 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。
- 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
- 数据链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。
我们编写的程序位于应用层,因此我们的程序是和TCP/UDP打交道的
1.1、描述TCP协议和UDP协议,并说出他们的区别与联系;
TCP协议和UDP协议是传输层的两种协议。Socket是传输层供给应用层的编程接口,所以Socket编程就分为TCP编程和UDP编程两类。
1.2.1、TCP
传输控制协议TCP(Transfer Control Protocol)是面向连接的,所谓面向连接,就是当计算机双方通信时必需经过先建立连接,然后传送数据,最后拆除连接三个过程。
在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。
-
第一步,是请求端(客户端)发送一个包含SYN即同步(Synchronize)标志的TCP报文,SYN同步报文会指明客户端使用的端口以及TCP连接的初始序号。
-
第二步,服务器在收到客户端的SYN报文后,将返回一个SYN+ACK的报文,表示客户端的请求被接受,同时TCP序号被加一,ACK即确认(Acknowledgement)。
-
第三步,客户端也返回一个确认报文ACK给服务器端,同样TCP序列号被加一,到此一个TCP连接完成。然后才开始通信的第二步:数据处理。
-
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。
1.2.2、UDP
基于TCP协议可以建立稳定连接的点对点的通信。这种通信方式实时、快速、安全性高,但是很占用系统的资源。由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时,不建议使用UDP协议。
特点:数据被限制在64kb以内,超出这个范围就不能发送了。
区别与联系;
在网络通讯中,TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据。是面向连接的,传输数据安全,稳定,效率相对较低。
UDP方式就类似于发送短信,使用这种方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端无法获得。是面向无连接的,传输数据不安全,效率较高。
这两种传输方式都在实际的网络编程中使用,重要的数据一般使用TCP方式进行数据传输,而大量的非核心数据则可以通过UDP方式进行传递,在一些程序中甚至结合使用这两种方式进行数据传递。
由于TCP需要建立专用的虚拟连接以及确认传输是否正确,所以使用TCP方式的速度稍微慢一些,而且传输时产生的数据量要比UDP稍微大一些。
基于客户机-服务器模式的应用场景
2、什么是客户机-服务器模式
2.1.客户端-服务器模式
定义:客户端-服务器模式(Client–server model)简称C/S结构,是一种网络架构,它把客户端 (Client) 与服务器 (Server) 区分开来。每一个客户端软件的实例都可以向一个服务器或应用程序服务器发出请求。
C/S结构:Client/Server结构(C/S结构)是大家熟知的客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。
代码如下(示例):
客户端进程:
这是一个过程,这通常使得信息请求。得到回应后,这一过程可能会终止或可能会做一些其他的处理。
例如: 互联网浏览器作为一个客户端应用程序,Web服务器发送一个请求到得到一个HTML网页。
服务器进程:
它接受一个来自客户端的请求的过程。获得来自客户端的请求后会处理所需的收集所需的信息,将其发送到请求客户端。一旦这样做完成后,就又变成准备为另一个客户端。服务器进程始终等待准备用于处理传入请求。
实例: Web服务器一直等待来自互联网浏览器的请求,并尽快得到任何请求从浏览器,它拿起一个请求的HTML页面,并把它发送回该浏览器。
注意,客户端需要知道的存在服务器的地址,但是服务器并不需要在建立的连接之前知道客户端的地址。一旦建立连接后,双方都可以发送和接收信息。
2.2、二层和三层架构:
有两种类型的客户端服务器架构:
- 两层构架: 在这种架构中,客户端直接与服务器进行交互。这种类型的架构可能有一些安全漏洞和性能问题。 IE浏览器和Web服务器的两层架构。这里的安全问题都解决了使用安全套接字层(SSL)。
- 三层架构:在这个架构中,多了一个软件位于客户端和服务器之间。这中间的软件被称为中间件。中间件被用来执行所有的安全检查和重负载情况下的负载平衡。中间件需要从客户端的所有请求,并做必要的验证后,通过向服务器发出请求。然后,服务器没有所需的处理和发送响应回中间件,中间件终于通过这个响应返回给客户端。如果想实现一个3层架构,那么可以使用如Web Logic或WebSphere软件在Web服务器和Web浏览器之间的任何中间件。
客户端特征:
- 主动的角色(主)。
- 发送要求。
- 等待直到收到回应。
服务器可是有状态或者无状态的。无状态的服务器不会保留任何两个请求之间的信息,有状态服务器会记住请求之间的信息。这些信息的作用域可以是全局的或者某个事务 (session)的。静态 HTML 页面服务器是一个无状态服务器的例子,Apache Tomcat 是一个有状态服务器。
服务器端与用户端的互动经常使用循序图描述,循序图是UML中的一个标准。
3.1、分析客户机-服务器模式优缺点,并详述客户机-服务器架构的程序设计方法(可结合程序流程图)。
优点:
- 更好地保护原有资源并共享C/S模式是一种开放式的结构,可有效地保护原有的软硬件资源;之前在其他环境上积累的数据和软件均可在C/S中通过集成而得以保留和使用;用户不仅可以存取服务器上的资源,也可存取其他客户机上的资源。
- 快速处理信息当用户提出一项请求时,可由多个服务器并行进行处理,提高响应速度;也可将一项任务分解,由客户和服务器分别处理,共同合作完成。
- 客户机和服务器均可单独自由升级
缺点:
- 客户与服务器数据数据库之间的互连支持能力有限,不同的数据库管理系统之间难以共享数据。同时,由于客户端集成了对数据的处理和显示功能,如果更新程序,则每台客户机上的软件都要更新,否则就会出错,无形中加大了软件分发和更新困难,增加了工作量和出错的概率。
- 将任务分开处理,系统本身也被分为若干部分,增大系统开发和管理的复杂程度与难度,增加了服务器的管理和支持人员的开销。
3.2客户机-服务器架构的程序设计方法
基于TCP协议的Socket编程和通信
在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序,简称客户端,而在第一次通讯中等待连接的程序被称作服务器端(Server)程序,简称服务器。一旦通讯建立,则客户端和服务器端完全一样,没有本质的区别。
1. Socket类:发送TCP消息。
2. ServerSocket类:创建服务器。
套接字是一种进程间的数据交换机制。这些进程既可以在同一机器上,也可以在通过网络连接的不同机器上。换句话说,套接字起到通信端点的作用。单个套接字是一个端点,而一对套接字则构成一个双向通信信道,使非关联进程可以在本地或通过网络进行数据交换。一旦建立套接字连接,数据即可在相同或不同的系统中双向或单向发送,直到其中一个端点关闭连接。套接字与主机地址和端口地址相关联。主机地址就是客户端或服务器程序所在的主机的IP地址。端口地址是指客户端或服务器程序使用的主机的通信端口。
在客户端和服务器中,分别创建独立的Socket,并通过Socket的属性,将两个Socket进行连接,这样,客户端和服务器通过套接字所建立的连接使用输入输出流进行通信
TCP/IP套接字是最可靠的双向流协议,使用TCP/IP可以发送任意数量的数据。
实际上,套接字只是计算机上已编号的端口。如果发送方和接收方计算机确定好端口,他们就可以通信了。
通过Socket的编程顺序:
1. 创建服务器ServerSocket,在创建时,定义ServerSocket的监听端口(在这个端口接收客户端发来的消息)。
2. ServerSocket调用accept()方法,使之处于阻塞状态。
3. 创建客户端Socket,并设置服务器的IP及端口。
4. 客户端发出连接请求,建立连接。
5. 分别取得服务器和客户端Socket的InputStream和OutputStream。
6. 利用Socket和ServerSocket进行数据传输。
7. 关闭流及Socket。
TCP:单向通信Socket之服务器端
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 最简单的服务器端代码
* @author Administrator
*/
public class BasicSocketServer {
public static void main(String[] args) {
Socket socket = null;
BufferedWriter bw = null;
try {
// 建立服务器端套接字:指定监听的接口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端建立监听");
// 监听,等待客户端请求,并愿意接收连接
socket = serverSocket.accept();
// 获取socket的输出流,并使用缓冲流进行包装
bw = new BufferedWriter(new
OutputStreamWriter(socket.getOutputStream()));
// 向客户端发送反馈信息
bw.write("hhhh");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭流及socket连接
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
TCP:单向通信Socket之客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
/**
* 最简单的Socket客户端
* @author Administrator
*/
public class BasicSocketClient {
public static void main(String[] args) {
Socket socket = null;
BufferedReader br = null;
try {
/*
* 创建Scoket对象:指定要连接的服务器的IP和端口而不是自己机器的
* 端口。发送端口是随机的。
*/
socket = new Socket(InetAddress.getLocalHost(), 8888);
//获取scoket的输入流,并使用缓冲流进行包装
br = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
//接收服务器端发送的信息
System.out.println(br.readLine());
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流及socket连接
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
UDP通讯的实现
▪ DatagramSocket:用于发送或接收数据报包
当服务器要向客户端发送数据时,需要在服务器端产生一个DatagramSocket对象,在客户端产生一个DatagramSocket对象。服务器端的DatagramSocket将DatagramPacket发送到网络上,然后被客户端的DatagramSocket接收。
DatagramSocket有两种常用的构造函数。一种是无需任何参数的,常用于客户端;另一种需要指定端口,常用于服务器端。如下所示:
DatagramSocket() :构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port) :创建数据报套接字并将其绑定到本地主机上的指定端口。
常用方法:
Ø send(DatagramPacket p) :从此套接字发送数据报包。
Ø receive(DatagramPacket p) :从此套接字接收数据报包。
Ø close() :关闭此数据报套接字。
▪ DatagramPacket:数据容器(封包)的作用
此类表示数据报包。 数据报包用来实现封包的功能。
常用方法:
Ø DatagramPacket(byte[] buf, int length) :构造数据报包,用来接收长度为 length 的数据包。
Ø DatagramPacket(byte[] buf, int length, InetAddress address, int port) :构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
Ø getAddress() :获取发送或接收方计算机的IP地址,此数据报将要发往该机器或者是从该机器接收到的。
Ø getData() :获取发送或接收的数据。
Ø setData(byte[] buf) :设置发送的数据。
UDP通信编程基本步骤:
1. 创建客户端的DatagramSocket,创建时,定义客户端的监听端口。
2. 创建服务器端的DatagramSocket,创建时,定义服务器端的监听端口。
3. 在服务器端定义DatagramPacket对象,封装待发送的数据包。
4. 客户端将数据报包发送出去。
5. 服务器端接收数据报包。
UDP:单向通信之客户端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class Client {
public static void main(String[] args) throws Exception {
byte[] b = "北京尚学堂".getBytes();
//必须告诉数据报包要发到哪台计算机的哪个端口,发送的数据以及数据的长度
DatagramPacket dp = new DatagramPacket(b,b.length,new
InetSocketAddress("localhost",8999));
//创建数据报套接字:指定发送信息的端口
DatagramSocket ds = new DatagramSocket(9000);
//发送数据报包
ds.send(dp);
//关闭资源
ds.close();
}
}
UDP:单向通信之服务器端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Server {
public static void main(String[] args) throws Exception {
//创建数据报套接字:指定接收信息的端口
DatagramSocket ds = new DatagramSocket(8999);
byte[] b = new byte[1024];
//创建数据报包,指定要接收的数据的缓存位置和长度
DatagramPacket dp = new DatagramPacket(b, b.length);
//接收客户端发送的数据报
ds.receive(dp); // 阻塞式方法
//dp.getLength()返回实际收到的数据的字节数
String string = new String(dp.getData(), 0, dp.getLength());
System.out.println(string);
//关闭资源
ds.close();
}
}