目录
概念:由点和线构成,表示诸多对象间的相互联系(ISO 国际开放组织)



UDP协议: User Datagram Protocol用户数据报协议 是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小64KB
注:更多关于TCP以及UDP的知识可以参考我的这篇博客幺:传输层(TCP三次握手以及四次挥手);TCP与UDP的区别_咸鱼乐的博客-CSDN博客
IP协议: Internet Protocol Address互联网协议地址/网络协议地址 分配给互联网设备的数字标签(唯一标识) IP地址分为两种:
IPV4: 4字节32位整数,并分成4段8位的二进制数,每8位之间用圆点隔开,每8位整数可以转换为一个0~255的十进制整数 格式: D.D.D.D 例如: 255.255.255.255
IPV6: 16字节128位整数,并分成8段十六进制数,每16位之间用圆点隔开,每6位整数可以转换为一个0~65535的十进制数 格式: X.X.X.X.X.X.X.X 例如: FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF
IPV4的应用分类

A类: 政府机构,1.0.0.1~126.255.255.254
B类: 中型企业,128.0.0.1~191.255.255.254
C类: 个人用户,192.0.0.1~223.255.255.254
D类: 用于组播,224.0.0.1~239.255.255.254
E类: 用于实验,240.0.0.1~255.255.255.254
回环地址: 127.0.0.1,指本机,一般用于测试使用
查看IP命令: ipconfig 测试IP命令: ping D.D.D.D
192.168.0.0 --- 192.168.255.255 (局域网搭建使用)
注:想更深入的了解IP地址的分类,以及七层模型可以看看我这篇文章:IP地址分类以及特殊ip地址(七层模型)_咸鱼乐的博客-CSDN博客_特殊ip地址
端口号: 在通信实体上进行网络通讯的程序的唯一标识 端口分类: 公认端口: 0~1023(固定端口) 注册端口: 1024~49151 动态或私有端口: 49152~65535 常用端口:
Mysql: 3306
Oracle: 1521
Tomact: 8080
SMTP: 25
Web服务器: 80
FTP服务器: 21
利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实 上的标准。
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标 识符套接字。
通信的两端都要有Socket,是两台机器间通信的端点。 网络通信其实就是Socket间的通信。
Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
Socket分类:
流套接字(stream socket):使用TCP提供可依赖的字节流服务
数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务

public Socket(InetAddress address,int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
public Socket(String host,int port)创建一个流套接字并将其连接到指定主机上的指定端口号。
public InputStream getInputStream()返回此套接字的输入流。可以用于接收网络消息
public OutputStream getOutputStream()返回此套接字的输出流。可以用于发送网络消息
public InetAddress getInetAddress()此套接字连接到的远程 IP 地址;如果套接字是未连接的,则返回 null。
public InetAddress getLocalAddress()获取套接字绑定的本地地址。 即本端的IP地址
public int getPort()此套接字连接到的远程端口号;如果尚未连接套接字,则返回 0。
public int getLocalPort()返回此套接字绑定到的本地端口。 如果尚未绑定套接字,则返回 -1。即本端的 端口号。
public void close()关闭此套接字。套接字被关闭后,便不可在以后的网络连接中使用(即无法重新连接 或重新绑定)。需要创建新的套接字对象。 关闭此套接字也将会关闭该套接字的 InputStream 和 OutputStream。
public void shutdownInput()如果在套接字上调用 shutdownInput() 后从套接字输入流读取内容,则流将 返回 EOF(文件结束符)。 即不能在从此套接字的输入流中接收任何数据。
public void shutdownOutput()禁用此套接字的输出流。对于 TCP 套接字,任何以前写入的数据都将被发 送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流, 则该流将抛出 IOException。 即不能通过此套接字的输出流发送任何数据。
客户端Socket的工作过程包含以下四个基本的步骤:
创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端 响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输
按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息 (但不能读取自己放入线路的信息),通过输出流将信息写入线程。
关闭 Socket:断开客户端到服务器的连接,释放线路
- package day8_12;
-
- import java.io.IOException;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.Socket;
- import java.util.Scanner;
-
- public class TestTcpSocket1 {
- public static void main(String[] args) throws IOException {
- // 连接服务端 (ip , 端口)
- // 连接本机的 9999 端口, 如果连接成功,返回 Socket 对象
- Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
- System.out.println( "客户端 socket=" + socket.getClass() );
- // 连接上后,生成 Socket, 通过 socket.getOutputStream()得到关联的输出流对象
- OutputStream outputStream = socket.getOutputStream();
- // 通过标准输出流,写入数据到 数据通道
- System.out.println("请输入你想发送的消息:");
- Scanner scanner = new Scanner(System.in);
- String str = scanner.nextLine();
- outputStream.write(str.getBytes());
- // 关闭流对象和 socket, 必须关闭
- outputStream.close();
- scanner.close();
- socket.close();
- System.out.println( "客户端退出" );
- }
-
- }
服务器程序的工作过程包含以下四个基本的步骤:
调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口 上。用于监听客户端的请求。
调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信 套接字对象。
调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出 流和输入流,开始网络数据的发送和接收。
关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字
- package day8_12;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.ServerSocket;
- import java.net.Socket;
-
- public class TestTcpSocket {
- public static void main(String[] args) {
- /* 编写一个服务器端
- 服务器端在9999端口监听;在本机 的 9999 端口监听, 等待连接
- 要求在本机没有其它服务在监听 9999
- 这个 ServerSocket 可以通过 accept() 返回多个 Socket[多个客户端连接服务器的并发]*/
- ServerSocket serverSocket = null;
- try {
- serverSocket = new ServerSocket(9999);
- System.out.println( "服务端,在9999端口监听,等待连接..." );
- // 当没有客户端连接 9999 端口时,程序会 阻塞, 等待连接;如果有客户端连接,则会返回 Socket 对象,程序继续
- Socket socket = serverSocket.accept();
- System.out.println( "服务端 socket=" + socket.getClass() );
- // 服务器端接收到客户端发送的信息,输出,并退出通过 socket.getInputStream() 读取客户端写入到数据通道的数据
- InputStream inputStream = socket.getInputStream();
- // IO 读取
- byte[] buf = new byte[1024];
- int readLen = 0;
- while ( (readLen=inputStream.read(buf))!=-1 ) {
- //根据读取到的实际长度,显示内容.
- System.out.println( new String(buf, 0, readLen) );
- }
- inputStream.close();
- socket.close();
- serverSocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证 UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP 地址和端口号以及接收端的IP地址和端口号。
UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和 接收方的连接。如同发快递包裹一样。
网络传输对象:
public DatagramSocket(int port)创建数据报套接字并将其绑定到本地主机上的指定端口。套接字将被 绑定到通配符地址,IP 地址由内核来选择。
public DatagramSocket(int port,InetAddress laddr)创建数据报套接字,将其绑定到指定的本地地址。 本地端口必须在 0 到 65535 之间(包括两者)。如果 IP 地址为 0.0.0.0,套接字将被绑定到通配符地 址,IP 地址由内核选择。
public void close()关闭此数据报套接字。
public void send(DatagramPacket p)从此套接字发送数据报包。DatagramPacket 包含的信息指示:将 要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
public void receive(DatagramPacket p)从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。 此方法 在接收到数据报前一直阻塞。数据报包对象的 length 字段包含所接收信息的长度。如果信息比包的 长度长,该信息将被截短。
public InetAddress getLocalAddress()获取套接字绑定的本地地址。
public int getLocalPort()返回此套接字绑定的本地主机上的端口号。
public InetAddress getInetAddress()返回此套接字连接的地址。如果套接字未连接,则返回 null。
public int getPort()返回此套接字的端口。如果套接字未连接,则返回 -1。
public DatagramPacket(byte[] buf,int length)构造 DatagramPacket,用来接收长 度为 length 的数据包。 length 参数必须小于等于 buf.length。
public DatagramPacket(byte[] buf,int length,InetAddress address,int port)构造数 据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。length 参数必须小于等于 buf.length。
public InetAddress getAddress()返回某台机器的 IP 地址,此数据报将要发往该 机器或者是从该机器接收到的。
public int getPort()返回某台远程主机的端口号,此数据报将要发往该主机或 者是从该主机接收到的。
public byte[] getData()返回数据缓冲区。接收到的或将要发送的数据从缓冲区 中的偏移量 offset 处开始,持续 length 长度。
public int getLength()返回将要发送或接收到的数据的长度。
DatagramSocket与DatagramPacket
建立发送端,接收端
建立数据包
调用Socket的发送、接收方法
关闭Socket
发送端与接收端是两个独立的运行程序
UDP服务器:
- package day8_12;
-
- import java.io.IOException;
- import java.net.*;
-
- public class TestUdpSocket {
- public static void main(String[] args) {
- DatagramSocket datagramSocket = null;
- System.out.println("基础版UDP服务器启动....");
- //定义UDP服务端socket
- while (true){
- try {
- datagramSocket = new DatagramSocket(8888);
- //接受客户端传递过来的容器
- byte[] contain = new byte[1024];
- //解包过程
- DatagramPacket datagramPacket = new DatagramPacket(contain,contain.length);
- //等待接受消息阻塞
- datagramSocket.receive(datagramPacket);
- //打印消息
- System.out.println(new String(contain,0,datagramPacket.getLength()));
- } catch (SocketException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (datagramSocket != null){
- datagramSocket.close();
- }
- }
- }
- }
- }
UDP客户端:
- package day8_12;
-
- import java.io.IOException;
- import java.net.*;
- import java.util.Scanner;
-
- public class TestUdpSocket1 {
- public static void main(String[] args) {
- DatagramSocket datagramSocket = null;
- Scanner sc = null;
- while (true){
- System.out.println("基础版UDP客户端启动....");
- //定义UDP客户端socket
- try {
- sc = new Scanner(System.in);
- datagramSocket = new DatagramSocket();
- //定义发送的消息
- String msg = sc.nextLine();
- //装包过程(注意:需要指定服务器端的IP和端口号)
- DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),
- msg.getBytes().length,
- InetAddress.getByName("localhost"),
- 8888);
- //发送消息
- System.out.println("消息发送中,发送的消息为: msg = " + msg);
- datagramSocket.send(datagramPacket);
- } catch (SocketException e) {
- e.printStackTrace();
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- //关闭连接
- datagramSocket.close();
- }
- }
- }