1-Java网络编程
1 网络分层
通过网络将数据从一台主机发送到另外的主机,这个过程是通过计算机网络通信来完成。网络通信的不同方面被分解为多个层,层与层之间用接口连接。
1.1 OSI模型
OSI模型把网络通信的工作分为7层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

OSI参考模型过于庞大,因此后续提出了TCP/IP协议栈参考模型,简化了OSI参考模型,由于TCP/IP协议栈的简单,获得了广泛的应用。
1.2 TCP/IP模型
TCP/IP,即Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,是Internet最基本的协议,Internet国际互联网络的基础。
TCP/IP协议是一个开放的网络协议簇,它的名字主要取自最重要的网络层IP协议和传输层TCP协议。TCP/IP协议定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。TCP/IP参考模型采用4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求,这4个层次分别是:网络接口层、网络层(IP层)、传输层(TCP层)、应用层。

-
网络接口层:在TCP/IP协议中,网络接口层位于第四层。由于网络接口层兼并了物理层和数据链路层所以,网络接口层既是传输数据的物理媒介,也可以为网络层提供一条准确无误的线路。该层负责接收IP数据报并进行传输,从网络上接收物理帧,抽取IP数据报转交给下一层
-
网络层(IP层):在TCP/IP协议中网络层可以进行网络连接的建立和终止以及IP地址的寻找等功能。该层负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机
-
传输层(TCP层):TCP层负责在应用进程之间建立端到端的连接和可靠通信,它只存在与端节点中。TCP层涉及两个协议,TCP和UDP。其中,TCP协议提供面向连接的服务,提供按字节流的有序、可靠传输,可以实现连接管理、差错控制、流量控制、拥塞控制等。UDP协议提供无连接的服务,用于不需要或无法实现面向连接的网络应用中。
-
应用层:应用层为Internet中的各种网络应用提供服务。
2 网络协议
2.1 TCP协议
TCP(传输控制协议)是面向连接的传输层协议。TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接(IP层协议不能提供这种能力,而是不可靠的数据交换)。TCP协议采用字节流传输数据。
2.1.1 TCP报文格式

- 源端口号以及目的端口号:各占2个字节,端口是传输层和应用层的服务接口,用于寻找发送端和接收端的进程,一般来讲,通过端口号和IP地址,可以唯一确定一个TCP连接,在网络编程中,通常被称为一个socket接口。
- 序号:Seq序号,占4个字节、32位。用来标识从TCP发送端向TCP接收端发送的数据字节流。发起方发送数据时对此进行标记。
- 确认序号:Ack序号,占4个字节、32位。包含发送确认的一端所期望收到的下一个序号。只有ACK标记位为1时,确认序号字段才有效,因此,确认序号应该是上次已经成功收到数据字节序号加1,即Ack=Seq + 1。
- 数据偏移:占4个字节,用于指出TCP首部长度,若不存在选项,则这个值为20字节,数据偏移的最大值为60字节。
- 保留字段占6位,暂时可忽略,值全为0。
- 标志位,6个
- URG(紧急):为1时表明紧急指针字段有效
- ACK(确认):为1时表明确认号字段有效
- PSH(推送):为1时接收方应尽快将这个报文段交给应用层
- RST(复位):为1时表明TCP连接出现故障必须重建连接
- SYN(同步):在连接建立时用来同步序号
- FIN(终止):为1时表明发送端数据发送完毕要求释放连接
- 接收窗口:占2个字节,用于流量控制和拥塞控制,表示当前接收缓冲区的大小。在计算机网络中,通常是用接收方的接收能力的大小来控制发送方的数据发送量。TCP连接的一端根据缓冲区大小确定自己的接收窗口值,告诉对方,使对方可以确定发送数据的字节数。
- 校验和:占2个字节,范围包括首部和数据两部分。
- 选项是可选的,默认情况是不选。
2.1.2 三次握手与四次挥手

三次握手示意图如上:
- 第一次握手(客户端发送请求):客户机发送连接请求报文段到服务器,并进入SYN_SENT状态,等待服务器确认。发送连接请求报文段内容:SYN=1,seq=x;SYN=1意思是一个TCP的SYN标志位置为1的包,指明客户端打算连接的服务器的端口;seq=x表示客户端初始序号x,保存在包头的序列号(Sequence Number)字段里。
- 第二次握手(服务端回传确认):服务器收到客户端连接请求报文,如果同意建立连接,向客户机发回确认报文段(ACK)应答,并为该TCP连接分配TCP缓存和变量。服务器发回确认报文段内容:SYN=1,ACK=1,seq=y,ack=x+1;SYN标志位和ACK标志位均为1,同时将确认序号(Acknowledgement Number)设置为客户的ISN加1,即x+1;seq=y为服务端初始序号y。
- 第三次握手(客户端回传确认):客户机收到服务器的确认报文段后,向服务器给出确认报文段(ACK),并且也要给该连接分配缓存和变量。此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。客户端发回确认报文段内容:ACK=1,seq=x+1,ack=y+1;ACK=1为确认报文段;seq=x+1为客户端序号加1;ack=y+1,为服务器发来的ACK的初始序号字段+1。
注意:握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。

四次挥手示意图如上,由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
- TCP客户端发送一个FIN,用来关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态。发送报文段内容:FIN=1,seq=u;FIN=1表示请求切断连接;seq=u为客户端请求初始序号。
- 服务端收到这个FIN,它发回一个ACK给客户端,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号;服务端进入CLOSE_WAIT状态。发送报文段内容:ACK=1,seq=v,ack=u+1;ACK=1为确认报文;seq=v为服务器确认初始序号;ack=u+1为客户端初始序号加1。
- 服务器关闭客户端的连接后,发送一个FIN给客户端,服务端进入LAST_ACK状态。发送报文段内容:FIN=1,ACK=1,seq=w,ack=u+1;FIN=1为请求切断连接,ACK=1为确认报文,seq=w为服务端请求切断初始序号。
- 客户端收到FIN后,客户端进入TIME_WAIT状态,接着发回一个ACK报文给服务端确认,并将确认序号设置为收到序号加1,服务端进入CLOSED状态,完成四次挥手。发送报文内容:ACK=1,seq=u+1,ack=w+1;ACK=1为确认报文,seq=u+1为客户端初始序号加1,ack=w+1为服务器初始序号加1。
注意:为什么连接的时候是三次握手,关闭的时候却是四次挥手?
因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭socket,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文,我收到了”。只有等到服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送,故需要四步挥手。
2.2 UDP协议
2.2.1 介绍
UDP,用户数据报协议,它是TCP/IP协议簇中无连接的运输层协议。
- UDP是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
- 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务器可同时向多个客户端传输相同的消息。
- UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
- 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
- UDP使用尽量最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表。
- UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部受就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。
2.2.2 报文格式

UDP协议由两部分组成:首部和数据。其中,首部仅有8个字节,包括源端口和目的端口、长度(UDP用于数据报的长度)、校验和。
2.2.3 TCP与UDP的区别
- TCP基于连接,UDP是无连接的;
- 对系统资源的要求,TCP较多,UDP较少;
- UDP程序结构较简单;
- TCP是流模式,而UDP是数据报模式;
- TCP保证数据正确性,而UDP可能丢包;TCP保证数据顺序,而UDP不保证;
3 Socket编程
3.1 Socket介绍
Java的网络编程主要涉及到的内容是Socket编程。Socket就是两台主机之间逻辑连接的端点。Socket是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议、本地主机的IP地址、本地进程的协议端口、远程主机的IP地址、远程进程的协议端口。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
“TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。这个就像操作系统会提供标准的编程接口,比如win32编程接口一样,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。”
3.2 Socket编程案例
下面是一个客户端和服务器端进行数据交互的简单例子,客户端输入正方形的边长,服务器端接收到后计算面积并返回给客户端。
服务器端
public class SocketServer {
public static void main(String[] args) throws IOException {
// 端口号
int port = 7000;
// 在端口上创建一个服务器套接字
ServerSocket serverSocket = new ServerSocket(port);
// 监听来自客户端的连接
Socket socket = serverSocket.accept();
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
do {
double length = dis.readDouble();
System.out.println("服务器端收到的边长数据为:" + length);
double result = length * length;
dos.writeDouble(result);
dos.flush();
} while (dis.readInt() != 0);
socket.close();
serverSocket.close();
}
}
客户端
public class SocketClient {
public static void main(String[] args) throws UnknownHostException, IOException {
int port = 7000;
String host = "localhost";
Socket socket = new Socket(host, port);
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
Scanner sc = new Scanner(System.in);
boolean flag = false;
while (!flag) {
System.out.println("请输入正方形的边长:");
double length = sc.nextDouble();
dos.writeDouble(length);
dos.flush();
double area = dis.readDouble();
System.out.println("服务器返回的计算面积为:" + area);
while (true) {
System.out.println("继续计算?(Y/N)");
String str = sc.next();
if (str.equalsIgnoreCase("N")) {
dos.writeInt(0);
dos.flush();
flag = true;
break;
} else if (str.equalsIgnoreCase("Y")) {
dos.writeInt(1);
dos.flush();
break;
}
}
}
socket.close();
}
}

浙公网安备 33010602011771号