Java中的网络编程(上)

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

第78节:Java中的网络编程(上)

前言

网络编程涉及ip,端口,协议,tcp和udp的了解,和对socket通信的网络细节.

网络编程

第78节:Java中的网络编程(上)

 

网络模型

OSI开放系统互连

第78节:Java中的网络编程(上)

 

网络通讯要素

网络编程指IO加网络

第78节:Java中的网络编程(上)

 

OSI模型

第78节:Java中的网络编程(上)

 

TCP/IP模型

第78节:Java中的网络编程(上)

 

描述

TCP/IP模型:

  1. 应用层
  2. 传输层
  3. 网际层
  4. 主机到网络层

OSI模型:(封装) 网络1封包->网络2拆包

  1. 应用层
  2. 表示层
  3. 会话层
  4. 传输层
  5. 网络层
  6. 数据链路层
  7. 物理层

网络通讯要素:

  1. ip地址
  2. 端口号
  3. 传输协议
第78节:Java中的网络编程(上)

 

网络通讯要素

主机名和ip地址是对应的,默认的主机名:localhost

1
2
3
4
5
6
7
8
9
10
11
java.netInetAddress
 
java.lang.Object
-> java.net.InetAddress
 
已实现的接口: Serializable
已知子类: Inet4Address, Inet6Address
 
public class InetAddress extends Object implements Serializable
该类表示互联网协议ip地址

 

ip地址是ip使用32或128位无符号数字,它是一种低级的协议,UDP和TCP协议都是在它的基础上构建的.

InetAddress的实例包含ip地址,相应的主机名

升级:

1
2
3
4
5
6
7
8
9
10
11
java.netInet6Address
 
java.lang.Object
-> java.net.InetAddress
-> java.net.Inet6Address
 
所有已实现的接口:Serializable
 
public final class Inet6Address extends InetAddress
该类表示互联网协议第6版地址

 

获取ip地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.dashucoding.ip;
 
import java.net.InetAddress;
import java.net.UnknownHostException;
 
public class IPDemo {
 
   public static void main(String[] args) throws UnknownHostException {
       // TODO Auto-generated method stub
       // ip地址对象 InetAddress
 
       // 获取本地主机地址对象
       InetAddress ip = InetAddress.getLocalHost();
       // 获取主机地址和主机名
       System.out.println(ip.getHostAddress() + ":" + ip.getHostName());
 
       InetAddress ip2 = InetAddress.getByName("192.168.2.151");
       // 获取主机地址和主机名
       System.out.println(ip.getHostAddress() + ":" + ip.getHostName());
 
       // 主机名是需要进行解析的
   }
 
}

域名解析_查表

1
C:WindowsSystem32driversetc
第78节:Java中的网络编程(上)

 

文件

第78节:Java中的网络编程(上)

 

Internet协议属性

DNS域名解析服务器,宽带服务.配置DNS域名服务器主机,一个网址浏览要到它的Ip地址,要找到,就会把ip地址放到DNS域名解析服务器,供给本地使用宽带连接的使用,就可以在浏览器中找到ip地址,浏览网址了.

DNS服务器软件,把你要浏览的地址ip写进去就可以了

有些软件需要进行注册序列号?

1
2
// hosts 文件配置
127.0.0.1 www.###.cn // 该域名地址

 

端口

端口,为物理端口,一台电脑发送信息给另一台电脑的软件,发送ip地址完, 要带上端口号, 然后 对应另一台接收消息的软件 有个软件应用程序的数字标识,为逻辑端口, 这样就可以对应发送到另一台电脑上的对应软件接收消息.

我今天要去一家酒店去了地址,到了楼层, 要知道哪个房间号,才知道对应做什么事.

第78节:Java中的网络编程(上)

 

端口号

传输协议

TCP和UDP: 传输协议,传输规则,通讯规则,传输层.

第78节:Java中的网络编程(上)

 

TCP和UDP

UDP,不需要建立连接.我发给你信息,不管你在不在,我就发给你了.我送你东西,写个地址,发到你家就行.有个包,装东西,有大小限制,最多是64k的限制数据.(好处,速度快,不可靠)

TCP发数据,要确保连接是不是畅通的.TCP是通过三次握手完成的,确保数据的连接畅通.用流行的话语:

完成了三次TCP握手:

女朋友发给男朋友
:"在吗?"

男朋友回复女朋友
:"我在!"

女朋友回复男朋友
:"我知道了"

这样爱情可靠,但是很浪费时间的,这样维护情感有点耗时,但是很可靠.

TCP断开就不传了,UDP不管.电话来形容TCP,对讲机来形容UDP.

Socket

第78节:Java中的网络编程(上)

 

Socket

Socke <-> Socket
数据在两者之间通过IO传输,传输协议TCP或UDP

Socket就像两端插口,传输协议不一样,Socket插口也是由不同的类型的.数据在两者之间进行传输,数据是基于网络的io流进行传输的,传输过程就是传入和传出的过程

UDP_发送端_out

 

1
2
3
4
5
6
7
8
9
10
11
12
java.net
Class DatagramSocket
java.lang.Object
-> java.net.DatagramSocket
 
All Implemented Interfaces: 
Closeable, AutoCloseable
已知直接子类:
MulticastSocket
 
public class DatagramSocket extends Object implements Closeable
该类为用于发送和接收数据报数据包的套接字,数据报套接字是分组传送服务的发送或接收点.

例子:

1
2
3
4
DatagramSocket s = new DatagramSocket(null); 
s.bind(new InetSocketAddress(8888));
 
DatagramSocket s = new DatagramSocket(8888);

 

构造方法摘要

方法 说明
DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口
DatagramSocket(DatagramSocketImpl impl) 使用指定的DatagramSocketImpl创建一个未绑定的数据报套接字
DatagramSocket(int port) 构造数据报套接字并将其绑定到本地主机上的指定端口
DatagramSocket(int port, InetAddress laddr) 创建一个数据报套接字,绑定到指定的本地地址
DatagramSocket(SocketAddress bindaddr) 创建一个数据报套接字,绑定到指定的本地套接字地址

receive(DatagramPacket p):从此套接字接收数据报包
send(DatagramPacket p):从此套接字发送数据报包

1
2
3
4
5
6
7
8
9
java.net
Class DatagramPacket
java.lang.Object
-> java.net.DatagramPacket
 
public final class DatagramPacket extends Object
该类表示数据报包
 
将数据封装到数据包中,数据包对象为DatagramPacket

数据包

1
2
DatagramPacket(byte[] buf, int length)
// 字节数组来的

构造一个DatagramPacket用于接收长度的数据包length.

1
2
3
4
5
receive
public void receive(DatagramPacket p) throws IOException
此套接字接收数据报包
返回, DatagramPacket的缓冲区填充了接收的数据
数据报包也包含发送的ip地址和发送方的端口号
第78节:Java中的网络编程(上)

发送端

第78节:Java中的网络编程(上)

接收端

UDPSend

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
34
package com.dashucoding.udp;
 
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
 
public class UDPSend {
 
   public static void main(String[] args) throws IOException {
 
       System.out.println("udp 发送端 run");
       // 先建立upd的socket 面向对象编程
       // 将数据封装到数据包中
       // 使用Socket对象的send方法
       // 将数据包发送出去
       // 关闭资源
       DatagramSocket ds = new DatagramSocket();
       // 数据
       String text = "我是发送端,发送的数据";
       // 将数据转成字节数组
       byte[] buf = text.getBytes();
       // 将字节数据封装到数据包中
       DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("你的ip地址"),10000);
       // 发送
       ds.send(dp);
       // 发完关掉,不然留着资源干嘛
       ds.close();
 
   }
 
}
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
34
35
36
37
38
39
package com.dashucoding.udp;
 
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
 
public class UDPRece {
 
   public static void main(String[] args) throws IOException {
       System.out.println("udp 接收端 run");
       // 定义udp接收数据,显示在屏幕上
       // 先有插座嘛,udpsocket服务
       // 接收数据前 -> 先将数据存储到数据包中
       // 先定义数据包
       // 数据包对象会获取数据包中的内容,发送端的ip和端口
       // 关闭资源
 
       // 有upsocket服务
       DatagramSocket ds = new DatagramSocket(10000);
       // 接收数据,接收字节数据
       byte[] buf = new byte[1024];
       // 定义包
       DatagramPacket dp = new DatagramPacket(buf, buf.length);
 
       // 还没存到数据包,进行存储
       ds.receive(dp); // 阻塞
 
       String ip = dp.getAddress().getHostAddress();
       int port = dp.getPort();
       String text = new String(dp.getData(),0,dp.getLength());
 
       System.out.println(ip+" : "+port+" : "+text);
       // 关闭资源
       ds.close();
 
   }
 
}
1
2
3
键盘录入
 
发送端:
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
34
35
36
package com.dashucoding.udp2;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
 
public class UDPSend2 {
 
   public static void main(String[] args) throws IOException {
       // TODO Auto-generated method stub
       System.out.println("udp2 发送端 run");
       DatagramSocket ds = new DatagramSocket();
       // 数据来源于键盘录入
       BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
       String line = null;
       while ((line = bufr.readLine()) != null) {
           if("over".equals(line)) {
               break;
           }
           // 将数据转成字节数组
           byte[] buf = line.getBytes();
           // 将字节数据封装到数据包中
           DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("你的ip地址"), 10002);
           ds.send(dp);
           // 发完关掉,不然留着资源干嘛
       }
 
       ds.close();
   }
 
}

接收端:

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.dashucoding.udp2;
 
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
 
public class UDPRece2 {
 
   public static void main(String[] args) throws IOException {
       // 有upsocket服务
       System.out.println("udp2 接收端 run");
       DatagramSocket ds = new DatagramSocket(10002);
       while (true) {
 
           // 接收数据,接收字节数据
           byte[] buf = new byte[1024];
           // 定义包
           DatagramPacket dp = new DatagramPacket(buf, buf.length);
 
           // 还没存到数据包,进行存储
           ds.receive(dp); // 阻塞
 
           String ip = dp.getAddress().getHostAddress();
           int port = dp.getPort();
           String text = new String(dp.getData(), 0, dp.getLength());
 
           System.out.println(ip + " : " + port + " : " + text);
           // 关闭资源
       }
       // ds.close();
   }
}

群聊工程

1
变化ip地址192.168.1.255

TCP

1
2
3
4
5
6
7
8
9
10
11
12
Socket()
通过系统默认类型的SocketImpl创建未连接套接字
 
Socket(InetAddress address, int port)
创建一个流套接字并将其连接到指定ip地址的指定端口
 
Socket(String host, int port)
创建一个流套接字并将其连接到指定主机上的指定端口号
 
getOutputStream()
 
返回此套接字的输出流

网络编程TCP服务端

第78节:Java中的网络编程(上)
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
package com.dashucoding.tcp;
 
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
 
public class TCPClient {
 
   public static void main(String[] args) throws UnknownHostException, IOException {
       // TODO Auto-generated method stub
       // 建立tcp的客户端socket 明确服务端的地址和端口
       // socket io流
       // 获取socket流
 
       System.out.println("客户端运行");
       // 建立tcp的客户端socket,明确服务端的地址和端口
       Socket s = new Socket("ip地址",20003);
       // socket输出流数据发送
       OutputStream out = s.getOutputStream();
       // 通过socket输出流将数据发送
       out.write("hello tcp 来了".getBytes());
       // 关闭
       s.close();
   }
 
}
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
34
35
36
37
38
39
40
41
42
43
package com.dashucoding.tcp;
 
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
public class TCPServer {
 
   public static void main(String[] args) throws IOException {
       // TODO Auto-generated method stub
       // 获取客户端的数据,在屏幕上
 
       // 思路
       // 创建服务端的socket,明确端口,监听一个端口
       // 服务端只要获取到链接过来的客户端就可以和指定的客户端通信了
       // 通过获取客户端的读取流对象读取客户端发来的数据.
       // 显示屏幕上
       System.out.println("服务端运行");
 
       // 创建服务端的socket,明确接收端口
       ServerSocket ss = new ServerSocket(20003);
 
       while (true) {
           // 服务端只要获取到连接过来的客户端就可以和指定的客户端通信
           Socket s = ss.accept();
           String ip = s.getInetAddress().getHostAddress();
           System.out.println(ip + "...connected");
 
           // 通过获取客户端的读取流对象读取客户端发送来的数据
           InputStream in = s.getInputStream();
           // 流操作
           byte[] buf = new byte[1024];
           int len = in.read(buf);
           String text = new String(buf, 0, len);
           System.out.println(text);
           // 关闭
           s.close();
       }
       // ss.close();
   }
 
}

客户端和服务端交互

客户端:

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
package com.dashucoding.tcp2;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
 
public class TCPClient2 {
 
   public static void main(String[] args) throws UnknownHostException, IOException {
       // TODO Auto-generated method stub
       // 实现客户端和服务端的收发过程
       System.out.println("客户端2 启动");
       // 创建客户端的socket对象 
       Socket s = new Socket("ip地址",20004);
       // 发送数据,通过socket输出流完成
       OutputStream out = s.getOutputStream();
       out.write("服务端,我来了".getBytes());
 
       // 读取服务端返回的数据,通过socket输入流
       InputStream in = s.getInputStream();
       byte[] buf=new byte[1024];
       int len = in.read(buf);
       String text = new String(buf,0,len);
       System.out.println(text);
 
       // 关闭资源
       s.close();
   }
 
}

服务端:

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
34
35
36
37
38
39
package com.dashucoding.tcp2;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
public class TCPServer2 {
 
   public static void main(String[] args) throws IOException {
       // TODO Auto-generated method stub
       System.out.println("服务端2 启动");
       // 创建tcp服务端socket明确端口
       ServerSocket ss = new ServerSocket(20004);
 
       while (true) {
           // 获取客户端
           Socket s = ss.accept();
           System.out.println(s.getInetAddress().getHostAddress() + "...");
 
           // 读取客户端的发送过来的数据
           InputStream in = s.getInputStream();
           byte[] buf = new byte[1024];
           int len = in.read(buf);
           String text = new String(buf, 0, len);
           System.out.println(text);
           // 给客户端回馈数据
           OutputStream out = s.getOutputStream();
           out.write("客户端,我已经收到".getBytes());
 
           // 关闭客户端
           s.close();
       }
       // 关闭服务端
       // ss.close();
   }
 
}
第78节:Java中的网络编程(上)

 

客户端

第78节:Java中的网络编程(上)

 

服务端

 

小结

网络编程到网络模型:一开始7层到4层

传输层的了解

网络通讯:

  1. ip:用于网络中主机的数字标识
  2. 端口:用于应用程序的数字标识
  3. 传输协议:用于数据传输的规则

TCP和UDP的区别

TCP: 面向连接,三次握手,速度慢,可靠
UDP: 面向无连接,速度快,不可靠

实现UDP的通信:

1
可以发送,又可以接收 DatagramSocket DatagramPacket 数据包对象

实现TCP传输:

客户端,服务端

客户端要明确服务端的ip+端口,而服务端要明确端口,通过accept的方法获取客户端对象.

结言

那么你是否掌握了,什么是tcp和udp,socket通信机制,以及ip,端口,协议.

原文始发于微信公众号(达叔与他的朋友们):第78节:Java中的网络编程(上)