计算机网络
概念
计算机网络:利用通信线路和通信设备,将地理位置不同的、功能独立的多台计算机互连起来,以功能完善的网络软件来实现资源共享和信息传递,就构成了计算机网络系统,实际就是多台可联网设备互相通信。
计算机网络最核心的部分是网络协议,具体内容请自行查阅相关课程书籍,本文仅介绍接下来要使用的TCP和UDP。
TCP协议
传输控制协议(TCP,Transmission Control Protocol),是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP连接三次握手
例子:看望女朋友
我:你在家吗?我去找你玩。
女朋友:在家,你来吧。
我:行,我这就过去。
TCP断开四次挥手
例子:看望完女朋友临别之际
我:宝儿,我要走了。
女朋友:你走吧。
女朋友(不舍):你真的要走吗?
我:再见。
UDP协议
用户数据报协议(UDP,User Datagram Protocol), 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。
网络通信要素
IP地址
在计算机网络中会有很多台电脑,如果你想发送数据给某一台,那么其必须要有能找到它的标识,这个标识就是IP地址,可以想象成现实生活中每个人都有独有的身份证一样,IP地址就是智能设备在计算机网络中的身份证。
IP地址由网络地址和主机地址组成,可以分为IPV4和IPV6,两者不同于IP地址数量。
具体IP地址分类方式请参阅相关书籍,本文仅列举一些特殊IP地址
- 0.0.0.0
所有不清楚的主机和目的网络的集合 - 255.255.255.255
限制广播地址 - 127.0.0.1
本机地址,主要用于测试 - 224.0.0.1
组播地址 - 169.254.x.x
如果你的主机使用了DHCP功能自动获得一个IP地址,那么当你的DHCP服务器发生故障,或响应时间太长而超出了一个系统规定的时间,Wingdows系统会为你分配这样一个地址 - 10.x.x.x、172.16.x.x~172.31.x.x、192.168.x.x
私有地址,这些地址被大量用于企业内部网络中
端口号
在计算机系统中,每个进程都会有自己对应的端口号,如果你通过IP地址找到某台主机并向访问其某个应用程序或是访问服务器的某个端口,这时你便需要其端口号进行操作。
端口号的范围在0-65535之间,其中有一些是常用服务的端口,网络中的通信协议也同样有相应的端口。
端口号小于256的定义为常用端口,大多数TCP/IP实现给临时端口号分配1024—5000之间的端口号,大于5000的端口号是为其他服务预留的。
URL
URL 代表着是统一资源定位符(Uniform Resource Locator)。就是本地资源在 Web 上的地址。
标准的 URL 地址由 protocol(协议)、hostname(域名或IP地址)、port(端口号)、path(路径)、parameters(参数)五部分组成。
注意:IP地址与域名是一对多的关系。 一个IP地址可以对应多个域名,但是一个域名只有一个IP地址。
URL下载网络资源实例
public class URLDown {
public static void main(String[] args) throws Exception {
//URL地址
URL url = new URL("https://m801.music.126.net/20210627210339/75038ca2053fc9232803efef10ee9170/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/7858189233/1ca7/8ea7/dbfe/00df8f6c121bcf45a2baeb054b44e1d7.m4a");
//以HTTP协议的方式打开URL连接
HttpURLConnection httpsURLConnection = (HttpURLConnection) url.openConnection();
//获取输入流,连接URL资源
InputStream inputStream = httpsURLConnection.getInputStream();
//新建文件输出流,连接本地文件
FileOutputStream fos = new FileOutputStream(new File("src/File/7.m4a"));
//输入流内容转入输出流中
inputStream.transferTo(fos);
//输出流以字节数组写入本地文件
fos.write(new byte[1024]);
//关闭资源
fos.close();
inputStream.close();
httpsURLConnection.disconnect();
}
}
TCP通信
TCP是面向连接的,有服务器和客户端之分,其主要涉及两个类ServerSocket(服务器)和Socket(客户端)。
核心流程
服务器端
1.新建ServerSocket并指定端口号
2.调用accept方法等待客户端连接
3.连接成功后调用getInputStream()获得输入流读取数据
4.关闭资源,后开先关
客户机端
1.新建Socket通过IP地址和端口号连接服务器端ServerSocket
2.调用getOutputStream()获得输出流输出数据
3.关闭资源
实例
服务器端
public class TCPServerSocket {
public static void main(String[] args) {
ServerSocket serverSocket=null;
Socket accept=null;
InputStream inputStream=null;
try {
//1.新建ServerSocket并指定端口号
serverSocket = new ServerSocket(9999);
//2.调用accept方法等待数据
accept = serverSocket.accept();
//3.接收到数据调用输入流读取数据
inputStream = accept.getInputStream();
System.out.println(new String(inputStream.readAllBytes()));
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭资源,后开先关
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(accept!=null){
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
客户机端
public class TCPSocket {
public static void main(String[] args) {
Socket socket=null;
OutputStream outputStream=null;
try {
//1.新建Socket连接服务器端
socket = new Socket(InetAddress.getLocalHost(), 9999);
//2.获取输出流输出数据
outputStream = socket.getOutputStream();
outputStream.write("Hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//3.关闭资源
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
UDP通信
UDP是无连接的,没有服务器和客户端之分。主要涉及两个类DatagramSocket和DatagramPacket。
核心流程
1.新建DatagramSocket
发送方直接新建即可
接收方需要指定接收端口号
2.新建DatagramPacket
发送方需要指定数据包、目的IP地址、目的端口号
接收方需要指定接收数据包大小
3. 数据发送和接收
发送方调用DatagramSocket的send方法将封装好的数据包DatagramPacket发送
接收方调用DatagramSocket的receive方法将接收的数据包存到自己的DatagramPacket中
4.关闭资源
多线程教学通信实例
发送端线程类
public class NetWorkSend implements Runnable {
//新建DatagramSocket发送平台
private DatagramSocket socket;
{
try {
socket = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
}
//新建Scanner获取输入数据
private Scanner scanner = new Scanner(System.in);
//获取ip地址和端口号
private String ip = null;
private int port = 0;
public NetWorkSend(String ip, int port) {
this.ip = ip;
this.port = port;
}
//多线程run方法
@Override
public void run() {
try {
String s = null;
while (true) {
//获取键盘输入
s = scanner.nextLine();
//将从键盘输入的数据加IP地址和端口号封装成DatagramPacket数据包
DatagramPacket datagramPacket = new DatagramPacket(s.getBytes(), 0, s.getBytes().length, InetAddress.getByName(this.ip), this.port);
//发送数据包
socket.send(datagramPacket);
//条件判断退出死循环
if (s.equals("bye")) break;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
scanner.close();
socket.close();
}
}
}
接收端线程类
public class NetWorkRecive implements Runnable {
//新建DatagramSocket接收平台
private DatagramSocket socket = null;
//初始化接收平台端口号
private String name = null;
public NetWorkRecive(int port, String name) {
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
this.name = name;
}
@Override
public void run() {
try {
byte[] bytes = new byte[1024];
while (true) {
//新建接收端DatagramPacket数据包
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
//接收数据包
socket.receive(packet);
//读取数据包数据
String s = new String(packet.getData(), 0, packet.getLength());
System.out.println(name + s);
//条件判断退出死循环
if (s.equals("bye")) break;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
socket.close();
}
}
}
学生端线程开启
public class NetWorkStudent {
public static void main(String[] args) {
//新建学生端发送和接收线程
new Thread(new NetWorkSend("localhost",9999)).start();
new Thread(new NetWorkRecive(8888,"老师:")).start();
}
}
老师端线程开启
public class NetWorkTeacher {
public static void main(String[] args) {
//新建老师端发送和接收线程
new Thread(new NetWorkSend("localhost",8888)).start();
new Thread(new NetWorkRecive(9999,"学生:")).start();
}
}
总结
网络通信最重要因素是IP地址和端口号,然后就可以进行网络通信,支撑其交换数据的核心技术是流,不论是实时数据交换还是URL资源获取。
-
Author
- 小葳宝贝最爱吃饭