JAVA网络编程-初始网络编程

本文最后更新于:April 24, 2022 pm

积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里,不积小流无以成江海。齐骥一跃,不能十步,驽马十驾,功不在舍。面对悬崖峭壁,一百年也看不出一条裂缝来,但用斧凿,能进一寸进一寸,能进一尺进一尺,不断积累,飞跃必来,突破随之。

目录

TCP和UDP

TCP协议

  • 使用TCP协议前,需要建立TCP连接,形成传输数据通道。
  • 传输前,会采用 “三次握手” 方式建立连接,所以是可靠的。
  • TCP协议进行通信的两个应用进程:客户端、服务端。
  • 在连接中可以进行大数据量的传输。
  • 传输完毕后,需要释放已建立的连接,效率低。(如打电话,你在通话时别人无法再次打通)

UDP协议

  • 将数据、源、目的封装成数据包,不需要建立连接。
  • 每个数据包的大小限制在64K内。
  • 不可靠的,因为无需连接。
  • 发送数据结束时无需释放资源,速度快。因为不需要连接,所以不需要释放。

三次握手和四次挥手

三次握手

  • 客户端–发送带有 SYN 标志的数据包–一次握手–服务端
  • 服务端–发送带有 SYN/ACK 标志的数据包–二次握手–客户端
  • 客户端–发送带有带有 ACK 标志的数据包–三次握手–服务端

SYN 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符 ,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。 ])消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。

三次握手的目的:建立可靠的通信信道,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。解释如下。

  • 第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常。

  • 第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常。

  • 第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常。

所以三次握手就能确认双发收发功能都正常,缺一不可。

四次挥手

断开一个 TCP 连接则需要“四次挥手”:

  • 客户端-发送一个 FIN,用来关闭客户端到服务器的数据传送。
  • 服务器-收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加1 。和 SYN 一样,一个 FIN 将占用一个序号。
  • 服务器-关闭与客户端的连接,发送一个FIN给客户端。
  • 客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加1。

任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。

InetAddress类

获取本机InetAddress对象

1
2
InetAddress inetAddress = InetAddress.getLocalHost();
System.out.println(inetAddress); //dragononedeMBP/192.168.43.252

根据主机名/域名获取IP地址对象

1
2
3
4
5
InetAddress dragononedeMBP = InetAddress.getByName("dragononedeMBP");
System.out.println(dragononedeMBP); //dragononedeMBP/192.168.43.252

InetAddress byName = InetAddress.getByName("www.baidu.com");
System.out.println(byName); //www.baidu.com/110.242.68.4

获取InetAddress对象的主机名

1
2
3
InetAddress byName = InetAddress.getByName("www.baidu.com");
String hostName = byName.getHostName();
System.out.println(hostName); //www.baidu.com

获取InetAddress对象的地址

1
2
3
InetAddress byName = InetAddress.getByName("www.baidu.com");
String hostAddress = byName.getHostAddress();
System.out.println(hostAddress); //110.242.68.4

套接字(Socket)

Socket开发网络应用程序被广泛使用。通信的两端都要有Socket,是两台机器间通信的端点。网络通信其实就是Socket间的通信。Socket运行程序把网络连接当成一个流,数据在两个Socket间通过IO传输。一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。

简单实现

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.networkTest;

import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
* @Author DragonOne
* @Date 2022/4/22 10:52
* @墨水记忆 www.tothefor.com
*/
public class SocketClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket(InetAddress.getLocalHost(), 9999); //或ip地址加端口
System.out.println("客户端的socket:"+socket.getClass());

OutputStream outputStream = socket.getOutputStream();
outputStream.write("我是客户端".getBytes());

outputStream.close();
socket.close();
System.out.println("客户端退出...");
}
}

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.networkTest;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
* @Author DragonOne
* @Date 2022/4/22 10:52
* @墨水记忆 www.tothefor.com
*/
public class SocketServer {

public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();
System.out.println("服务端的Socket为:"+accept.getClass());
byte[] bytes = new byte[1024];
int rlen = 0;
while((rlen=inputStream.read(bytes))!=-1){
System.out.println(new String(bytes,0,rlen));
}


inputStream.close();
accept.close();
serverSocket.close();
System.out.println("服务端退出...");
}
}