网络编程基础
网络编程
1.1概述
信件:
计算机网络:
计算机网络是指将地理位置不同的具有独立功能的多台计算机及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件以及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程的目的:
无线电台..传播交流信息,数据交换。通信
想达到这个效果需要什么:
1.如何准确的定位网络上的一台主机,利用IP地址加端口,再定位到这个计算机上的某个资源。
2.找到了这个主机,如何传输数据呢?
javaweb:网页编程 B/S
网络编程:TCP/IP
1.2网络通信的一些要素
如何实现网络的通信?
通信双方地址
- IP
- 端口号
规则:网络通信的协议
such HTTP,SMTP,TCP,IP,FTP
网络编程重点:TCP+UDP
小结:
- 网络编程中有二个主要的问题
1)如何准确的定位到网络上的一台或多台主机
2)找到主机后如何进行通信
2.网络编程中的要素
1)IP和端口号
2)网络通信协议
Java万物皆对象,端口号可以自己new。
要学习的呢是IP,Port的类,UDP,TCP的类
1.3 IP
ip地址的类:InetAddress(没有构造方法,不能new,只能使用它的静态方法)
IP含义:唯一定位一台网络上计算机。
127.0.0.1:本机localhost
ip地址的分类
ipv4 -- 127.0.0.1, 4个字节组成,每个字节长度为0~225.
ipv6 -- 240e:398:5ba5:6b00:8042:8ce2:8df6:419b
128位,8个无符号整数
公网(互联网)-- 私网(局域网)
192.168.xx.xx 专门给组织内部使用的
1.4端口
端口表示计算机上的一个程序的进程;根据端口可以找到互相通信的应用程序
PID(Port ID):进程ID;
一栋楼是一个IP,每一户人家是一个端口号,电脑上的资源相当于家里面的小物件。
被规定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
netstat- ano // DOS命令查询端口使用情况
netstat- ano|findstr "8080" // |为管道,查看端口是非被占用(查看指定的端口)
tasklist|findstr "8080" // 查看指定端口的进程
每次程序启动,进程号是随机的,端口号是唯一的。
类:InetSocketAddress
构造方法:InetSocketAddress(InetAdress,Socket)such as new InetSocketAddress("127.0.0.1",8080);
1.5通信协议
协议:约定,就想我们现在说的是普通话。
(传输层)
TCP:用户传输协议
UDP:用户数据报协议
TCP/UDP对比:
TCP:打电话
· 连接稳定
· 三次握手,四次挥手
最少需要三次,保证稳定连接
A:你瞅啥
B:瞅你咋的?
A:干一场
四次挥手:
A:我不发了(关闭发送)
B:好,那我不收了(关闭连接)
B:我不发了(关闭发送)
A:好,那我不收了(关闭连接)
· 客户端,服务端
·传输完成,释放连接,效率低
UDP:发短信
· 不连接,不稳定
· 客户端,服务端没有明确的界限
· 不管有没有准备好,都可以发给你
· 导弹
·DDOS:洪水攻击!(饱和攻击)
1.6TCP
客户端
1.连接服务器Socket
2.发送消息
// 客户端
public class TcpSocketCilent {
public static void main(String[] args) throws Exception {
// 1. 要知道服务器的地址,端口号
InetAddress serverIp = InetAddress.getByName("localhost");
int port = 9999;
// 2.创建一个Socket连接
Socket socket = new Socket(serverIp, port);
// 3.发送信息IO流
OutputStream os = socket.getOutputStream();
os.write("hellohujesse4".getBytes());
os.close();
}
}
服务器
1.建立服务的端口ServerSocket
2.等待用户的连接accept
3接受用的消息
//服务端
public class TcpSocketServer {
public static void main(String[] args) throws IOException {
try(
// 我有一个地址
ServerSocket serverSocket = new ServerSocket(9999);
//等待客户端连接过来
Socket socket = serverSocket.accept();
//读取客户端的信息
InputStream in = socket.getInputStream();
//管道流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
){
byte []buffer=new byte[1024];
int len;
while((len=in.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
}catch (Exception e){
e.printStackTrace();
}}}
1.7文件上传
服务器端
package com.hujesse.netAddres;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
// 服务端接受文件
public class FileUploadServer {
public static void main(String[] args) throws Exception{
try(
// 1创建服务(端口)
ServerSocket serverSocket =new ServerSocket(9000);
//2 监听客户端的连接
Socket socket = serverSocket.accept(); // 阻塞式监听
// 3获取输入流
InputStream is = socket.getInputStream();
//4 文件输出
FileOutputStream fos = new FileOutputStream(new File("FileUploadImg.jpg"));
){
int len;
byte [] data = new byte[1024];
while((len=is.read(data))!=-1){
fos.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace(); } }}
客户端
package com.hujesse.netAddres;
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 FileUploadCilent {
public static void main(String[] args) throws Exception{
try(
// 1 创建一个socket连接
Socket socket =new Socket(InetAddress.getByName("127.0.0.1"),9000);
// 2创建一个输出流
OutputStream os = socket.getOutputStream();
// 3读取文件
FileInputStream fis = new FileInputStream(new File("2.jpg"));
){
//4 写出文件
byte [] buffer = new byte[1024];
int len;
while((len=fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
}catch (Exception e){
e.printStackTrace(); } }}
1.8 Tomcat
服务端:
·自定义 S
· Tomcat服务器 S
客户端
· 自定义 C
· 浏览器 B
通过前面的例子我们可以发现,服务端可以自己编写或者使用别人写的Tomcat
1.9 UDP
发短信:不用连接,需要知道对方的地址
udp传输数据就好像在大海上运输货物,DatagramSocket就像的两个通信港口的码头,DatagramPacket就像在两端运输货物的轮船
发送端(send)
- 创建DatagramSocket,随机端口号
- 创建DatagramPacket,制定数据,长度,地址和端口
- 使用DatagramSocket发送DatagramPacket
- 关闭DatagramSocket
- 异常处理
package com.internet;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class udp_receive {
public static void main(String[] args) throws IOException {
DatagramSocket datagramSocket = new DatagramSocket(1111);
DatagramPacket datagramPacket = new DatagramPacket(new byte[1024],1024);
datagramSocket.receive(datagramPacket); //接收数据
byte[] arr = datagramPacket.getData(); //获取数据
int len=datagramPacket.getLength(); //获取有效长度
System.out.println(new String(arr,0,len));
datagramSocket.close(); //关闭(码头)
}
}
接收端(receive)
- 创建DatagramSocket,匹配端口号
- 创建DatagramPacket,创建接收数据和有效数据长度
- 接收socket
- 接收packet
- 关闭DatagramSocket
不存在具体的客户端和服务端(互相都可以传)
package com.hujesse.netAddres;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
// 不需要连接服务器
public class UDPFileTrans {
public static void main(String[] args )throws Exception {
//1 建立一个Socket
DatagramSocket socket = new DatagramSocket();//创建DatagramSocket(码头)
//2 建个包 + 发送给谁
InetAddress localhost =InetAddress.getByName("127.0.0.1");
int port = 9090;
String message = "helloBro"; //要发送的数据(货物)
DatagramPacket datagramPacket = new DatagramPacket(message.getBytes(),0,message.getBytes().length,localhost,port);
//创建DatagramPacket,相当于货轮,将数据打包(要发送的数据,数据的长度,Ip地址,端口)
// 3发送包
socket.send(datagramPacket);
// 4 关闭流
socket.close();
}}
“服务端”
package com.hujesse.netAddres;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UdpServerTrans {
public static void main(String[] args) throws Exception{
// 开放端口
DatagramSocket datagramSocket = new DatagramSocket(9090); //创建(码头)
// 接受数据包,还是要等待客户端的连接🔗
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, 0, data.length);//创建DatagramPacket(集装箱)
datagramSocket.receive(packet);// 阻塞接受
System.out.println(new String(packet.getData()));
// 关闭连接
datagramSocket.close(); }}
UDP聊天实现
循环发送消息
package com.hujesse.netAddres;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
// sender
public class UDPChat {
public static void main(String[] args) throws Exception{
DatagramSocket socket = new DatagramSocket(8888);
// 准备数据:控制台读取System.in
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true) {
String data = reader.readLine();
DatagramPacket packet = new DatagramPacket(data.getBytes(), 0, data.getBytes().length, new InetSocketAddress("localhost", 6666));
socket.send(packet);
if(data.equals("bye")){
break;
}
}
socket.close(); }}
循环接受消息
package com.hujesse.netAddres;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
// recive
public class UDPChat2 {
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[] data = packet.getData();
String receiveData = new String(data,0,data.length);
System.out.println(receiveData);
// 断开连接 bye
if(data.equals("bye")){
break;
} }
socket.close(); }}
UDP实现多线程聊天
线程载体发送端sender
package com.hujesse.netAddres;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class MuiltiChat implements Runnable{
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIp;
private int toPort;
public MuiltiChat(int fromPort, String toIp, int toPort) {
this.fromPort = fromPort;
this.toIp = toIp;
this.toPort = toPort;
try {
socket =new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
}catch (Exception e){
e.printStackTrace();
} }
@Override
public void run() {
while (true) {
try {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIp,this.toPort));
socket.send(packet);
if(datas.equals("bye")){
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close(); }}
线程载体接收端recive
package com.hujesse.netAddres;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class MuiltiChat2 implements Runnable{
DatagramSocket socket = null;
private int port;
private String msgFrom;
public MuiltiChat2(int port,String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try{
socket = new DatagramSocket(port);
}catch (Exception e){
e.printStackTrace();
} }
@Override
public void run() {
while (true){
try{
byte [] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
socket.receive(packet);
byte[] data = packet.getData();
String receiveData = new String(data,0, data.length);
System.out.println(msgFrom+" : "+receiveData);
if(receiveData.equals("bye")){
break;
}
}catch (Exception e){
}}
socket.close();
}}
线程实例化学生
package com.hujesse.netAddres;
// 学生即可以接受也可以发送所以有二个
public class TalkStudent {
public static void main(String[] args) {
//学生发送
new Thread(new MuiltiChat(5555,"localhost",8888)).start();
//学生接受
new Thread(new MuiltiChat2(9999,"student")).start();
}
}
线程实例化老师
package com.hujesse.netAddres;
// 老师即发送又接受,发送占一个端口,接受占一个端口
public class TalkTeacher {
public static void main(String[] args) {
//老师发送
new Thread(new MuiltiChat(7777,"localhost",9999)).start();
//老师接受
new Thread(new MuiltiChat2(8888,"teacher")).start();
}
}
2.0 URL
https://www.bilibili.com/video/BV1LJ411z7vY?p=12
统一资源定位符,定位互联网上的某一个资源
DNS域名解析:将www.baidu.com -->转换为一个IP
协议://ip地址:端口/项目名/资源
2.01下载网络资源
package com.hujesse.netAddres;
import java.io.*;
import java.net.URL;
public class URLtest {
public static void main(String[] args) throws IOException {
//1下载地址
URL url =new URL("https://i0.hdslb.com/bfs/vc/fb9521333b8ea79d90bdfc6da31cf83c52d93ec9.png");
try(
// 2连接到这个资源 HTTP
InputStream is = url.openStream();
// 3先保存到内存流里面
ByteArrayOutputStream bo = new ByteArrayOutputStream();
){
byte [] buffer = new byte[1024];
int len;
while ((len=is.read(buffer))!=-1){
bo.write(buffer,0,len);
}
// 再将内存流里面的数据写入文件
try(
FileOutputStream fos = new FileOutputStream(new File("Bilibili.png"));
){
byte [] data = bo.toByteArray();
fos.write(data);
}catch (Exception e){
e.printStackTrace();
}
}catch (Exception e){
e.printStackTrace();
} }}