







类别 | 最大网络数值 | IP地址范围 | 单个网段最大主机数 | 私有IP地址范围 |
A | 126(2^7-2) | 1.0.0.1-127.255.255.254 | 16777214 | 10.0.0.0-10.255.255.255 |
B | 16384(2^14) | 128.0.0.1-191.255.255.254 | 65534 | 172.16.0.0-172.31.255.255 |
C | 2097152(2^21) | 192.0.0.1-223.255.255.254 | 254 | 192.168.0.0-192.168.255.255 |
目前主流使用的IP地址是IPV4,但是随着网络规模的不断扩大,IPV4面临着枯竭的危险,所以推出了IPV6。
IPV4,采用32位地址长度,只有大约43亿个地址,它只有4段数字,每一段最大不超过255。随着互联网的发展,IP地址不够用了,在2019年11月25日IPv4位地址分配完毕。
IPv6采用128位地址长度,几乎可以不受限制地提供地址。按保守方法估算IPv6实际可分配的地址,整个地球的每平方米面积上仍可分配1000多个地址。

总结



UDP | TCP | |
是否连接 | 无连接 | 面向连接 |
是否可靠 | 不可靠传输,不使用流量控制和拥塞控制 |
可靠传输,使用流量控制和拥塞控制
|
连接对象个数 |
支持一对一,一对多,多对一和多对多交
互通信
|
只能是一对一通信
|
传输方式 |
面向报文
|
面向字节流
|
首部开销 |
首部开销小,仅 8 字节
|
首部最小 20 字节,最大 60 字节
|
适用场景 |
适用于实时应用( IP 电话、视频会议、直
播等)
|
适用于要求可靠传输的应用,例如文
件传输
|
public class InetTest {
public static void main(String[] args)throws Exception {
//实例化InetAddress对象
InetAddress inetAddress = InetAddress.getLocalHost();
//返回当前计算机的IP地址
System.out.println(inetAddress.getHostAddress());
//返回当前计算机名
System.out.println(inetAddress.getHostName());
}
}
根据域名获取计算机的信息
public class InetTest2 {
public static void main(String[] args)throws Exception {
InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress.getHostAddress());
System.out.println(inetAddress.getHostName());
}
}
根据IP获取计算机的信息
public class InetTest3 {
public static void main(String[]
args)throws Exception {
InetAddress inetAddress =
InetAddress.getByName("14.215.177.38");
System.out.println(inetAddress.getHostAddress());
System.out.println(inetAddress.getHostName());
}
}
InetSocketAddress的使用
public class InetSocketTest {
public static void main(String[] args) {
InetSocketAddress inetSocketAddress = new InetSocketAddress("www.baidu.com",80);
System.out.println(inetSocketAddress.getAddress().getHostAddress());
System.out.println(inetSocketAddress.getHostName());
}
}
URL的使用
public class UrlTest {
public static void main(String[] args)throws Exception {
URL url = new URL("https://www.itbaizhan.com/search.html? kw=java");
System.out.println("获取与此URL相关联协议的默认端口:"+url.getDefaultPort());
System.out.println("访问资源:"+url.getFile());
System.out.println("主机名"+url.getHost());
System.out.println("访问资源路径:"+url.getPath());
System.out.println("协议:"+url.getProtocol());
System.out.println("参数部分:"+url.getQuery());
}
}
通过URL实现最简单的网络爬虫
public class UrlTest2{
public static void main(String[] args)throws Exception {
URL url = new URL("https://www.itwwd.com/");
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
StringBuilder sb = new StringBuilder();
String temp;
/*
* 这样就可以将网络内容下载到本地机器。
* 然后进行数据分析,建立索引。这也是搜索引擎的第一步。
*/
while ((temp = br.readLine()) != null) {
sb.append(temp);
}
System.out.println(sb);
} catch (Exception e) {
e.printStackTrace();
}
}
}

TCP/IP通信连接的简单过程:
public class BasicSocketServer {
public static void main(String[] args) {
System.out.println("服务器启动等待监听。。。。");
//创建ServerSocket
try(ServerSocket ss =new ServerSocket(8888);
//监听8888端口,此时线程会处于阻塞状态。
Socket socket = ss.accept();
//连接成功后会得到与客户端对应的Socket对象,并解除线程阻塞。
//通过客户端对应的Socket对象中的输入流对象,获取客户端发送过来的消息。
BufferedReader br = new BufferedReader(new
InputStreamReader(socket.getInputStream()))){
System.out.println(br.readLine());
}catch(Exception e){
e.printStackTrace();
System.out.println("服务器启动失败。。。。");
}
}
}
创建客户端
public class BasicSocketClient {
public static void main(String[] args) {
//创建Socket对象
try(Socket socket =new Socket("127.0.01",8888);
//创建向服务端发送消息的输出流对象。
PrintWriter pw = new PrintWriter(socket.getOutputStream())){
pw.println("服务端,您好!");
pw.flush();
}catch(Exception e){
e.printStackTrace();
}
}
}
public class OneWaySocketServer {
public static void main(String[] args) {
System.out.println("服务端启动,开始监听听。。。。。");
try(ServerSocket serverSocket = new ServerSocket(8888);
//监听8888端口,获与取客户端对应的Socket对象
Socket socket = serverSocket.accept();
//通过与客户端对应的Socket对象获取输入流对象
BufferedReader br = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
//通过与客户端对应的Socket对象获取输出流对象
PrintWriter pw = new PrintWriter(socket.getOutputStream())){
System.out.println("连接成功!");
while(true){
//读取客户端发送的消息
String str = br.readLine();
System.out.println("客户端说:"+str);
if("exit".equals(str)){
break;
}
pw.println(str);
pw.flush();
}
}catch(Exception e){
e.printStackTrace();
System.out.println("服务端启动失败。。。。。");
}
}
}
创建客户端
public class OneWaySocketClient {
public static void main(String[] args) {
//获取与服务端对应的Socket对象
try(Socket socket = new Socket("127.0.0.1",8888);32
//创建键盘输入对象
Scanner scanner = new Scanner(System.in);
//通过与服务端对应的Socket对象获取输出流对象
PrintWriter pw = new PrintWriter(socket.getOutputStream());
//通过与服务端对应的Socket对象获取输入流对象
BufferedReader br = new BufferedReader(new
InputStreamReader(socket.getInputStream()))){
while(true){
//通过键盘输入获取需要向服务端发送的消息
String str = scanner.nextLine();
//将消息发送到服务端
pw.println(str);
pw.flush();
if("exit".equals(str)){
break;
}
//读取服务端返回的消息
String serverInput = br.readLine();
System.out.println("服务端返回的:"+serverInput);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
TCP双向通信
public class TwoWaySocketServer {
public static void main(String[] args) {
System.out.println("服务端启动!监听端口8888。。。。");
try(ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
//创建键盘输入对象
Scanner scanner = new Scanner(System.in);
//通过与客户端对应的Socket对象获取输入流对象
BufferedReader br = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
//通过与客户单对应的Socket对象获取输出流对象
PrintWriter pw = new PrintWriter(socket.getOutputStream());){
while(true){
//读取客户端发送的消息
String str = br.readLine();
System.out.println("客户端说:"+str);
String keyInput =
scanner.nextLine();
//发送到客户端
pw.println(keyInput);
pw.flush();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
创建客户端
public class TwoWaySocketClient {
public static void main(String[] args) {35
try(Socket socket = new Socket("127.0.0.1", 8888);
//创建键盘输入对象
Scanner scanner = new Scanner(System.in);
//通过与服务端对应的Socket对象获取输入流对象
BufferedReader br = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
//通过与服务端对应的Socket对象获取输出流对象
PrintWriter pw = new PrintWriter(socket.getOutputStream());){
while (true) {
String keyInput = scanner.nextLine();
pw.println(keyInput);
pw.flush();
String input = br.readLine();
System.out.println("服务端说:" + input);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
创建点对点的聊天应用
创建服务端
/**
* 发送消息线程
*/
class Send extends Thread{
private Socket socket;
public Send(Socket socket){
this.socket = socket;
}
@Override
public void run() {
this.sendMsg();
}
/**
* 发送消息
*/
private void sendMsg(){
//创建Scanner对象
try(Scanner scanner = new Scanner(System.in);
//创建向对方输出消息的流对象
PrintWriter pw = new PrintWriter(this.socket.getOutputStream());)
{
while(true){
String msg = scanner.nextLine();
pw.println(msg);
pw.flush();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 接收消息的线程
*/
class Receive extends Thread{
private Socket socket;
public Receive(Socket socket){
this.socket = socket;
}
@Override
public void run() {
this.receiveMsg();
}
/**
* 用于接收对方消息的方法
*/
private void receiveMsg(){
//创建用于接收对方发送消息的流对象
try(BufferedReader br = new BufferedReader(new
InputStreamReader(this.socket.getInputStream()));){
while(true){
String msg = br.readLine();
System.out.println("他说:"+msg);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public class ChatSocketServer {
public static void main(String[] args) {
try(ServerSocket serverSocket = new ServerSocket(8888);){
System.out.println("服务端启动,等待连接。。。。。");
Socket socket = serverSocket.accept();
System.out.println("连接成功!");
new Send(socket).start();
new Receive(socket).start();
}catch(Exception e){
e.printStackTrace();
}
}
}
创建客户端
/**
* 用于发送消息的线程类
*/
class ClientSend extends Thread{
private Socket socket;
public ClientSend(Socket socket){
this.socket = socket;
}
@Override
public void run() {
this.sendMsg();
}
/**
* 发送消息
*/
private void sendMsg(){
//创建Scanner对象
try(Scanner scanner = new Scanner(System.in);
//创建向对方输出消息的流对象
PrintWriter pw = new
PrintWriter(this.socket.getOutputStream());){
while(true){
String msg = scanner.nextLine();
pw.println(msg);
pw.flush();
}
}catch(Exception e){
e.printStackTrace();40
}
}
}
/**
* 用于接收消息的线程类
*/
class ClientReceive extends Thread{
private Socket socket;
public ClientReceive(Socket socket){
this.socket = socket;
}
@Override
public void run() {
this.receiveMsg();
}
/**
* 用于接收对方消息的方法
*/
private void receiveMsg(){
//创建用于接收对方发送消息的流对象
try(BufferedReader br = new BufferedReader(new
InputStreamReader(this.socket.getInputStream()));){
while(true){
String msg = br.readLine();
System.out.println("他说:"+msg);
}
}catch(Exception e){
e.printStackTrace();41
}
}
}
public class ChatSocketClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 8888);
System.out.println("连接成功!");
new ClientSend(socket).start();
new ClientReceive(socket).start();
}catch(Exception e){
e.printStackTrace();
}
}
}
优化点对点聊天应用
/**
* 发送消息线程
*/
class Send extends Thread{
private Socket socket;
private Scanner scanner;
public Send(Socket socket,Scanner scanner){
this.socket = socket;
this.scanner = scanner;42
}
@Override
public void run() {
this.sendMsg();
}
/**
* 发送消息
*/
private void sendMsg(){
//创建向对方输出消息的流对象
try(PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){
while(true){
String msg = scanner.nextLine();
pw.println(msg);
pw.flush();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 接收消息的线程
*/
class Receive extends Thread{
private Socket socket;43
public Receive(Socket socket){
this.socket = socket;
}
@Override
public void run() {
this.receiveMsg();
}
/**
* 用于接收对方消息的方法
*/
private void receiveMsg(){
//创建用于接收对方发送消息的流对象
try(BufferedReader br = new BufferedReader(new
InputStreamReader(this.socket.getInputStream()))){
while(true){
String msg = br.readLine();
System.out.println("他说:"+msg);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public class GoodTCP {
public static void main(String[] args){
Scanner scanner = null;
ServerSocket serverSocket = null;44
Socket socket = null;
try{
scanner = new Scanner(System.in);
System.out.println("请输入:server,<port> 或者:<ip>,<port>");
String str = scanner.nextLine();
String[] arr = str.split(",");
if("server".equals(arr[0])){
//启动服务端
System.out.println("TCP Server Listen at "+arr[1]+" .....");
serverSocket = new ServerSocket(Integer.parseInt(arr[1]));
socket = serverSocket.accept();
System.out.println("连接成功!");
}else{
//启动客户端
socket = new Socket(arr[0],Integer.parseInt(arr[1]));
System.out.println("连接成功!");
}
//启动发送消息的线程
new Send(socket,scanner).start();
//启动接收消息的线程
new Receive(socket).start();
}catch(Exception e){
e.printStackTrace();
}finally{
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
一对多应用
一对多应用设计
各socket对间独立问答,互相间不需要传递信息。
一对多应答型服务器
/**
* 定义消息处理线程类
*/
class Msg extends Thread{
private Socket socket;
public Msg(Socket socket){
this.socket = socket;
}
@Override
public void run() {
this.msg();
}
/**
* 将从客户端读取到的消息写回给客户端
*/
private void msg(){
try(BufferedReader br = new BufferedReader(new
InputStreamReader(this.socket.getInputStream()));
PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){
while(true){
pw.println(br.readLine()+" [ok]");47
pw.flush();
}
}catch(Exception e){
e.printStackTrace();
System.out.println(this.socket.getInetAddress()+" 断线了!");
}
}
}
public class EchoServer {
public static void main(String[] args) {
try(ServerSocket serverSocket = new ServerSocket(8888)){
//等待多客户端连接
while(true){
Socket socket = serverSocket.accept();
new Msg(socket).start();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
一对多聊天服务器
2. 服务器的线程设计
创建一对多聊天服务应用
/**
* 接收客户端消息的线程类
*/
class ChatReceive extends Thread{
private Socket socket;
public ChatReceive(Socket socket){
this.socket =socket;
}
@Override
public void run() {
this.receiveMsg();
}
/**
* 实现接收客户端发送的消息
*/
private void receiveMsg(){
try(BufferedReader br = new BufferedReader(new
InputStreamReader(this.socket.getInputStream()))){
while(true){
String msg = br.readLine();
synchronized ("abc"){
//把读取到的数据写入公共数据区
ChatRoomServer.buf="
["+this.socket.getInetAddress()+"] "+msg;
//唤醒发送消息的线程对象。
"abc".notifyAll();
}
}
}catch(Exception e){50
e.printStackTrace();
}
}
}
/**
* 向客户端发送消息的线程类
*/
class ChatSend extends Thread{
private Socket socket;
public ChatSend(Socket socket){
this.socket = socket;
}
@Override
public void run() {
this.sendMsg();
}
/**
* 将公共数据区的消息发送给客户端
*/
private void sendMsg(){
try(PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){
while(true){
synchronized ("abc"){
//让发送消息的线程处于等待状态
"abc".wait();
//将公共数据区中的消息发送给客户端51
pw.println(ChatRoomServer.buf);
pw.flush();
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public class ChatRoomServer {
//定义公共数据区
public static String buf;
public static void main(String[] args) {
System.out.println("Chat Server Version 1.0");
System.out.println("Listen at 8888.....");
try(ServerSocket serverSocket = new ServerSocket(8888)){
while(true){
Socket socket = serverSocket.accept();
System.out.println("连接
到:"+socket.getInetAddress());
new ChatReceive(socket).start();
new ChatSend(socket).start();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
UDP通信的实现和项目案例
UDP通信实现原理

方法名
|
使用说明
|
DatagramPacket(byte[] buf, int length)
|
构造数据报包,用来接收长度为 length 的数据包
|
DatagramPacket(byte[] buf, int length,
InetAddress address, int port)
|
构造数据报包,用来将长度为 length 的包发送到指
定主机上的指定端口号
|
getAddress()
|
获取发送或接收方计算机的 IP 地址,此数据报将要
发往该机器或者是从该机器接收到的
|
getData()
|
获取发送或接收的数据
|
setData(byte[] buf)
|
设置发送的数据
|
DatagramSocket:用于发送或接收数据报包
方法名
|
使用说明
|
send(DatagramPacket p)
|
从此套接字发送数据报包
|
receive(DatagramPacket p)
|
从此套接字接收数据报包
|
close()
|
关闭此数据报套接字
|
UDP通信编程基本步骤:
1. 创建客户端的DatagramSocket,创建时,定义客户端的监听端口。
2. 创建服务器端的DatagramSocket,创建时,定义服务器端的监听端口。
3. 在服务器端定义DatagramPacket对象,封装待发送的数据包。
4. 客户端将数据报包发送出去。
5. 服务器端接收数据报包。
public class UDPServer {
public static void main(String[] args) {
//创建服务端接收数据的DatagramSocket对象
try(DatagramSocket datagramSocket = new DatagramSocket(9999)){
//创建数据缓存区
byte[] b = new byte[1024];
//创建数据报包对象
DatagramPacket dp =new DatagramPacket(b,b.length);
//等待接收客户端所发送的数据
datagramSocket.receive(dp);
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str);
}catch(Exception e){
e.printStackTrace();
}
}
}
创建客户端
public class UDPClient {
public static void main(String[] args) {
//创建数据发送对象 DatagramSocket,需要指定消息的发送端口
try(DatagramSocket ds = new DatagramSocket(8888)) {
//消息需要进行类型转换,转换成字节数据类型。
byte[] b = "程序员".getBytes();
//创建数据报包装对象DatagramPacket
DatagramPacket dp = new DatagramPacket(b, b.length, new InetSocketAddress("127.0.0.1", 9999));
//发送消息
ds.send(dp);
}catch(Exception e){
e.printStackTrace();
}
}
}
传递基本数据类型
创建服务端
public class BasicTypeUDPServer {
public static void main(String[] args) {
try(DatagramSocket datagramSocket = new DatagramSocket(9999)){
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
datagramSocket.receive(dp);
//实现数据类型转换
try(DataInputStream dis = new DataInputStream(new ByteArrayInputStream(dp.getData()))){
//通过基本数据数据流对象获取传递的数据
System.out.println(dis.readLong());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
创建客户端
public class BasicTypeClient {
public static void main(String[] args) {
long n = 2000L;
try(DatagramSocket datagramSocket = new DatagramSocket(9000);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos)){
dos.writeLong(n);
//将基本数据类型数据转换成字节数组类型
byte[] arr = bos.toByteArray();
DatagramPacket dp = new DatagramPacket(arr,arr.length,new InetSocketAddress("127.0.0.1",9999));
datagramSocket.send(dp);
}catch (Exception e){
e.printStackTrace();
}
}
}
传递自定义对象类型
/**
* 当该对象需要在网络上传输时,一定要实现 Serializable接口
*/
public class Person implements Serializable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
创建服务端
public class ObjectTypeServer {
public static void main(String[] args) {
try(DatagramSocket datagramSocket = new DatagramSocket(9999);){
byte[] b = new byte[1024];
DatagramPacket dp = new DatagramPacket(b,b.length);
datagramSocket.receive(dp);
//对接收的内容做类型转换
try(ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(dp.getData()))){
System.out.println(objectInputStream.readOb
ject());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
创建客户端
public class ObjectTypeClient {
public static void main(String[] args) {
try(DatagramSocket datagramSocket = new DatagramSocket(8888);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)){
Person p = new Person();
p.setName("Oldlu");
p.setAge(18);
oos.writeObject(p);
byte[] arr = bos.toByteArray();
DatagramPacket dp = new DatagramPacket(arr,arr.length,new InetSocketAddress("127.0.0.1",9999));
datagramSocket.send(dp);
}catch(Exception e){
e.printStackTrace();
}
}
}