网络编程
1. 计算机网络
是指将地理位置不同的具有独立功能的多台计算机及其外部设备**,**通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
2. 网络通信的要素
2.1 通信双方的地址:
-
IP
-
端口号
2.2 通信的规则:网络通信协议
HTTP、TCP、UDP、FTP、SMTP…
TCP/IP参考模型:
OSI模型是理想化模型,并未得到全面应用,实际应用主要是TCP/IP模型
3. IP地址
-
唯一定位一台网络上的计算机
-
127.0.0.1 本机localhost
-
IP地址分类
-
IPV4/IPV6
-
IPV4:xxx.xxx.xxx.xxx(例:127.0.0.1)
四个字节组成 每个字节表示28即0-255,32位,总共可表示2(4*8)-1大概42亿个地址。在2011年就已用完
-
IPV6:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
128位,总共可表示2^(8*16)-1个地址
-
-
公网-私网
ABCD四类地址
公网用于互联网的使用,私网用于局域网的使用
192.168.xx.xx一般都为局域网
-
-
域名:解决IP的记忆问题
写写代码喽
package com.chen.lesson1;
import java.net.InetAddress;
import java.net.UnknownHostException;
//测试IP
public class TestInetAddress {
public static void main(String[] args) {
try {
//查询本机地址
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress2 = InetAddress.getByName("localhost");
System.out.println(inetAddress2);
InetAddress inetAddress3 = InetAddress.getLocalHost();
System.out.println(inetAddress3);
//返回百度的ip
InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress4);
//常用方法
System.out.println(inetAddress4.getCanonicalHostName()); //获得规范的名字 IP
System.out.println(inetAddress4.getHostAddress()); //获得主机的地址 IP
System.out.println(inetAddress4.getHostName()); //获得主机的名字 域名
} catch (UnknownHostException e){
e.printStackTrace();
}
}
}
4. 端口
表示计算机上的一个程序的进程
-
不同的进程有不同的端口号,用来区分软件。
-
被规定为0~65535
-
分为TCP端口和UDP端口,每个都是0~65535,同一协议下,端口号不能冲突。
-
端口分类
-
公有端口:0~1023 一般会被一些内置的进程使用
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
-
程序注册端口:1024~49151,分配给用户或者程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
-
动态/私有端口:49152~65535
-
DOS命令:
netstat -ano #查看所有端口
netstat -ano|findstr "5900" #查找指定的端口
tasklist|findstr "1448" #查看指定端口对应的进程
5. 通信协议
网络传输的通信协议很多
TCP/IP簇:实际上是一组协议
其中重要的几个协议
- TCP:用户传输协议
- UDP:用户数据报协议
- IP:网络互联协议
TCP UDP对比
TCP类似于打电话
- 需要连接,较稳定
三次握手四次挥手
最少需要三次才能保证稳定连接
A:发送连接请求 我能和你连接吗?
B:回应A的连接请求 可以!
A:回应B的回应 那我就连接了
断开连接需要四次
A:我要断开了
B:你真的要断开了吗?
B:你真的真的要断开了吗?
A:我真的要断开了
- 客户端、服务端
- 传输完成,释放连接 效率低
UDP类似于发短信
- 不需要连接,不稳定
- 客户端、服务端:没有明确的界限
- 不管有没有准备好 都可以发送
6. TCP
客户端
1.通过Socket连接服务器
2.发送消息
3.先启动服务端,后启动客户端
package com.chen.lesson2;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
//客户端
public class TcpClientDemo1 {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
try {
//1.要知道服务器的地址 端口号
InetAddress severIP = InetAddress.getByName("127.0.0.1");
int port = 9999;
//2.创建一个Socket连接
socket = new Socket(severIP,port);
//3.发送消息 IO流
os = socket.getOutputStream();
os.write("hello".getBytes());
} catch (Exception e) {
e.printStackTrace();
}finally {
//关闭资源
if (os!=null){
try {
os.close();
}catch (IOException e){
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
}
服务器
1.建立服务的端口 ServerSocket
2.等待用户的连接 通过accept
3.接收用户的消息
package com.chen.lesson2;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TcpServerDemo1 {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
Socket accept = null;
InputStream is = null;
ByteArrayOutputStream bos = null;
try {
//1.得有一个地址
serverSocket = new ServerSocket(9999);
while (true){
//2.等待客户端链接过来
accept = serverSocket.accept();
//3.读取客户端的消息
is = accept.getInputStream();
//管道流
bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
bos.write(buffer,0,len);
}
System.out.println(bos.toString());
}
}catch (IOException e){
e.printStackTrace();
}finally {
//关闭资源
if (bos!=null){
try {
bos.close();
}catch (IOException e){
e.printStackTrace();
}
}
if (is!=null){
try {
is.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();
}
}
}
}
}
客户端向服务端发送本地文件,服务端接收到文件并存储到本地
客户端
1.建立连接
2.建立输出流
3.通过文件输入流读取本地文件
4.通过输出流发送给服务端
5.关闭资源
package com.chen.lesson2;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
//客户端 往服务端发送文件 后启动客户端
public class TcpClientDemo2 {
public static void main(String[] args) throws Exception{
//1.创建一个Socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9900);
//2.创建一个输出流
OutputStream os= socket.getOutputStream();
//3.读取文件 文件路径在项目下
FileInputStream fis = new FileInputStream("img.jpg");
//4.写出文件
byte[] bytes = new byte[1024];
int len;
while ((len=fis.read(bytes)) != -1){
os.write(bytes,0,len);
}
//5.关闭资源
fis.close();
os.close();
socket.close();
}
}
服务端
1.建立服务端
2.监听客户端的连接
3.建立输入流
4.通过文件输出流,将读取到的客户端文件输出到本地
5.关闭资源
package com.chen.lesson2;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端 接收客户端的文件 先启动服务端
public class TcpServerDemo2 {
public static void main(String[] args) throws Exception{
//1.创建服务
ServerSocket serverSocket = new ServerSocket(9900);
//2.监听客户端的连接
Socket accept = serverSocket.accept();//阻塞式监听,会一直等待客户端连接
//3.建立输入流
InputStream is = accept.getInputStream();
//4.建立文件输出流 输出接收到的文件至项目下
FileOutputStream fos = new FileOutputStream("receive.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len=is.read(bytes)) != -1){
fos.write(bytes,0,len);
}
//5.关闭资源
fos.close();
is.close();
accept.close();
}
}
Tomcat
服务端
- 自定义 Server
- Tomcat服务器 Server
客户端
- 自定义 Client
- 浏览器 Browser
7. UDP
类似发短信,不用连接,但要知道对方地址
发送接收消息
发送端
package com.chen.lesson3;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
//UDP发送信息 无论对方接收甚至存在与否 都可以发送
//UDP不需要连接服务器 UDP没有真正的服务器和客户端的概念
public class UdpSendDemo1 {
public static void main(String[] args) throws Exception {
//1.建立一个Socket
DatagramSocket socket = new DatagramSocket();
//2.建立一个包
String msg = "你好呀!服务器!";
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 8080;
DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,address,port); //内容(byte数组)、起始位置、结束位置、对方IP、对方端口
//3.发送包
socket.send(packet);
//4.关闭流
socket.close();
}
}
接收端
package com.chen.lesson3;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//接收信息的一方
public class UdpReceiveDemo1 {
public static void main(String[] args) throws Exception {
//1.开放端口
DatagramSocket socket = new DatagramSocket(8080);
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length); //接收信息的包
socket.receive(packet); //阻塞接收
//输出地址信息
System.out.println(packet.getAddress().getHostName());
//打印内容信息
System.out.println(new String(packet.getData(),0,packet.getLength()));
//System.out.println(new String(bytes));
//3.关闭流
socket.close();
}
}
循环发送接收消息
循环发送消息 输入bye程序才结束
发送端
package com.chen.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class UdpSendDemo1 {
public static void main(String[] args) throws Exception {
//1.建立Socket
DatagramSocket socket = new DatagramSocket(8080);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
//2.建立包
String data = reader.readLine();
byte[] bytes = data.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress("127.0.0.1",9999));
//3.发送包
socket.send(packet);
//如果发送bye 结束程序
if (data.equals("bye")){
break;
}
}
//4.关闭流
socket.close();
}
}
接收端
package com.chen.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpReceiveDemo1 {
public static void main(String[] args) throws Exception {
//1.建立Socket
DatagramSocket socket = new DatagramSocket(9999);
while (true){
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
socket.receive(packet); //阻塞式接收
String s = new String(bytes,0,packet.getLength()); //如果用bytes.length() 若输入1个字节 则s接收到的是1个字节+1023个空
System.out.println(s);
System.out.println(bytes[100]);
//如果接收到bye 结束程序
if (s.equals("bye")){
break;
}
}
//3.关闭流
socket.close();
}
}
8. URL
URL即统一资源定位系统,用于定位互联网上某一资源
构成要素: 协议://ip地址:端口/项目名/资源
使用URL下载网页上的歌曲资源
package com.chen.lesson4;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class URLDown {
public static void main(String[] args) throws IOException {
//1.下载地址 网易云音乐-Wake
URL url = new URL("https://m701.music.126.net/20220509213930/ae77ea763c2d34e6ce5cf43e457e4c36/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/14096439655/28ac/f25c/345c/ed719def976100fb58df123e947133f2.m4a");
//2.连接到这个资源
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("Wake.m4a");
byte[] bytes = new byte[1024];
int len;
while ((len=inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,len);//写入文件
}
fileOutputStream.close();
inputStream.close();
urlConnection.disconnect();//断开连接
}
}