学习内容:
- 什么是计算机网络
- 网络通信的两个要素
- IP地址
- 端口Port
- 通信协议
- TCP实现聊天
- TCP文件上传实现
- UDP消息发送
- UDP聊天实现
- UDP在线咨询
- URL
学习笔记:
1.什么是计算机网络
概念:
指将地理位置不同的具有 独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
网络编程的目的:
传播交流信息,数据交换,进行通信等。
两个问题:
- 如何准确的定位网络上的一台或者多台主机
- 找到主机之后如何进行通信
Javaweb: 网页编程 B/S
网络编程:TCP/IP C/S
2.网络通信的要素
如何实现网络的通信?
1.通信双方的地址:
- ip
- 端口号
2.规则:网络通信的协议
TCP/IP模型:
3.IP地址
IP地址:InetAddress
- 唯一定位一台网络上计算机
- 本机localhost
- IP地址的分类:
- ipv4/ipv6
- IPV4 127.0.0.1 ,4个直接组成 ,0~255 , 42亿,三十e在北美,四e在亚洲。2011年就用尽;
- IPV6 fe80:915d:470e:d522:4339:fe4d:db39:1984,写成8个无符号整数,每个整数用四个十六进制位表示,
- 公网-私网
公网地址(万维网使用)和私有地址(局域网使用)。
192.168.开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用。
- ipv4/ipv6
- 域名:记忆IP问题
- IP:www.baidu.com
package com.bilibili;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TestInetAdress {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress inetAddress1= InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress3= InetAddress.getByName("localhost");
System.out.println(inetAddress1);
InetAddress inetAddress4= InetAddress.getLocalHost();
System.out.println(inetAddress4);
//查询网站ip地址
InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress2);
//常用方法
System.out.println(inetAddress2.getAddress());
System.out.println(inetAddress2.getCanonicalHostName());//规范名字
System.out.println(inetAddress2.getHostAddress());//ip
System.out.println(inetAddress2.getHostName());//域名,或者自己电脑的名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
输出结果:
/127.0.0.1
/127.0.0.1
Wym-forever2003/192.168.137.1
www.baidu.com/39.156.66.18
[B@1055e4af
39.156.66.18
39.156.66.18
www.baidu.com
4.端口Port
- 不同的进程有不同的端口号!用来区分软件!
- 端口号标识正在计算机上运行的进程(程序)。
- 被规定为一个 16 位的整数 0~65535。
- 端口分类:
- 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
- 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
- 动态/私有端口:49152~65535。
- 端口号与IP地址的组合得出一个网络套接字:Socket。
- 使用Socket注意事项:
- 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
- 通信的两端都要有Socket,是两台机器间通信的端点。
- 网络通信其实就是Socket间的通信。
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
package com.bilibili;
import java.net.InetSocketAddress;
public class TestInetSocketAdress {
public static void main(String[] args) {
InetSocketAddress SocketAddress = new InetSocketAddress("127.0.0.1",8080);
InetSocketAddress SocketAddress2 = new InetSocketAddress("localhost",8080);
System.out.println(SocketAddress);
System.out.println(SocketAddress2);
System.out.println(SocketAddress.getAddress());
System.out.println(SocketAddress.getHostName());
System.out.println(SocketAddress.getPort());
}
}
输出结果:
/127.0.0.1:8080
localhost/127.0.0.1:8080
/127.0.0.1
127.0.0.1
8080
5.通信协议
TCP通信协议
传输控制协议 (Transmission Control Protocol)
- TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过"三次握手”
- 三次握手: TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠
- 第一次握手:客户端向服务器端发出连接请求,等待服务器确认
- 第二次握手:服务器端向客户端回送一个响应, 通知客户端收到了连接请求
- 第三次握手:客户端再次向服务器端发送确认信息,确认连接
- 完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。例如.上传文件、下载文件、 浏览网页等
UDP协议
用户数据报协议(User Datagram Protocol) - UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输 - 例如视频会议通常采用UDP协议, 因为这种情况即使偶尔丢失一两个数据包, 也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
6.TCP实现聊天
服务端:
package com.bilibili;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpDemo01 {
public static void main(String[] args) throws Exception {
//1.我有一个地址
ServerSocket serverSocket = new ServerSocket(9999);
//2.等待客户端连接过来
Socket socket = serverSocket.accept();
//3.读取客户端的消息
InputStream is = socket.getInputStream();
//管道流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer)) != -1) {
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
if (baos != null) {
baos.close();
is.close();
socket.close();
serverSocket.close();
}
}
}
客户端:
package com.bilibili;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TcpDemo02 {
public static void main(String[] args) throws Exception {
//1.知道服务器的地址
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
//2.端口号
int port = 9999;
//3.创建一个socket连接
Socket socket = new Socket(serverIP,port);
//4.发送消息
OutputStream os = socket.getOutputStream();
os.write("你好世界".getBytes());
os.close();
socket.close();
}
}
输出结果
你好世界
7.TCP文件上传实现
服务器端:
package com.bilibili;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpDemo03 {
public static void main(String[] args) throws Exception {
//创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//监听客户端的连接
Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端连接
//获取输入流
InputStream is = socket.getInputStream();
//文件输出
FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer,0,len);
}
//通知客户端接收完毕
OutputStream os = socket.getOutputStream();
os.write("我接受到了~".getBytes());
//关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
客户端:
package com.bilibili;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TcpDemo04 {
public static void main(String[] args) throws Exception, Exception {
// 创建一个连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
// 创建一个输出流
OutputStream os = socket.getOutputStream();
// 文件流
FileInputStream fis = new FileInputStream(new File("C:\\Users\\Lenovo\\Pictures\\Camera Roll\\底图.jpg"));
// 写出文件
byte[] buffer = new byte[1024];
int len;
while ((len=fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
//通知服务器,我已经完毕
socket.shutdownOutput();
//确定服务器接收完毕,才可以断开连接
InputStream inputStream = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte [2014];
int len2;
while ((len2 = inputStream.read(buffer2)) != -1) {
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
// 关闭资源
baos.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
输出结果
有两个结果:
首先是控制台:
我接受到了~
然后是在stady文件夹下面
有一个receive.jpg文件
其内容和底图.jpg一样。
8.UDP消息发送
发送端
package com.bilibili;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpDemo01 {
//不需要连接服务器
public static void main(String[] args) throws Exception {
//建立一个socket
DatagramSocket socket = new DatagramSocket();
//建一个包
String msg = "你好,服务器!";
InetAddress localhost=InetAddress .getByName("localhost");
int port = 8080;
DatagramPacket packet= new DatagramPacket(msg.getBytes(), 0,msg.getBytes().length,localhost,port);
//发送包
socket.send(packet);
//关闭流
socket.close();
}
}
接收端
package com.bilibili;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpDemo02 {
public static void main(String[] args) throws Exception {
// 开放端口
DatagramSocket socket = new DatagramSocket(8080);
//接收数据包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0,buffer.length);
socket.receive(packet);//阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
//关闭连接
socket.close();
}
}
输出结果:
127.0.0.1
你好,服务器!
9.UDP聊天实现
发送端:
package com.Chart;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.channels.DatagramChannel;
public class UdpDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
//准备数据
BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
while (true) {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost", 6666));
socket.send(packet);
if(data.trim().equals("bye")) {
break;
}
}
socket.close();
}
}
接收端:
package com.Chart;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UpdDemo02 {
public static void main(String[] args)throws Exception {
DatagramSocket Socket = new DatagramSocket(6666);
while (true) {
//准备接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
Socket.receive(packet);//阻塞式接收包裹
//断开连接
byte[] date = packet.getData();
String receivedata = new String(date,0,date.length);
System.out.println(receivedata);
if(receivedata.trim().equals("bye")) {
break;
}
}
}
}
输出结果:
10.UDP在线咨询
接收端:
public class TalkReceive implements Runnable {
DatagramSocket socket;
private String msgFrom;
public TalkReceive(int port, String msgFrom) throws SocketException {
this.msgFrom = msgFrom;
socket = new DatagramSocket(port);
}
@Override
public void run() {
try {
while (true) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
byte[] data = packet.getData();
String datas = new String(data, 0, packet.getLength());
System.out.println(this.msgFrom + ":" + datas);
if (datas.equals("bye")) {
socket.close();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
发送端:
public class TalkSend implements Runnable {
DatagramSocket socket;
BufferedReader reader;
private String toIp;
private int toPort;
public TalkSend(int fromPort, String toIp, int toPort) throws SocketException {
this.toIp = toIp;
this.toPort = toPort;
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
}
@Override
public void run() {
try {
while(true) {
//从控制台读取信息
byte[] bytes = reader.readLine().getBytes();
//创建数据包
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.toIp, this.toPort));
socket.send(packet);
//退出循环
if (new String(bytes).equals("bye")) {
socket.close();
reader.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
启动:
public class TalkTeacher {
public static void main(String[] args) throws SocketException {
String host = "localhost";
new Thread(new TalkSend(9999,host,8888)).start();
new Thread(new TalkReceive(9000,"学生")).start();
}
}
public class TalkStudent {
public static void main(String[] args) throws SocketException {
String host = "localhost";
//开启两个线程,既可以发送又可以接收
new Thread(new TalkSend(8000,host,9000)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
11.URL
package com.bilibili;
import java.net.URL;
public class URLDemo01 {
public static void main(String[] args)throws Exception {
URL url = new URL("https://blog.csdn.net/Lalune_YM/article/details/125548469?spm=1001.2014.3001.5501");
System.out.println(url.getProtocol());//协议
System.out.println(url.getHost());//主机ip
System.out.println(url.getPort());//端口
System.out.println(url.getPath());//文件
System.out.println(url.getFile());//全路径
System.out.println(url.getQuery());//参数
}
}