网络编程
1.1、概述
地球村:
对地球的一种比喻说法。现代科技的迅速发展,缩小了地球上的时空距离,国际交往日益频繁便利,因而整个地球就如同是茫茫宇宙中的一个小村落。
计算机网络:
是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程的目的:
无线电台…传播交流信息,数据交换。通信。
想要达到的效果需要什么:
- 如何准确的定位网络上的一台电脑 192.168.16.124:端口,定位到这个计算机上的某个资源。
- 找到这个主机,如何传输数据呢?
javaweb:网页编程 BS
网络编程:TCP/IP CS
1.2、网络通信的要素
如何实现网络通信?
需要知道通信双方地址:
- ip 192.168.1.1
- 端口号
- 192.168.16.24:5900
规则:网络通信协议
TCP/IP 参考模型
小结:
- 网络编程中有两个主要问题
- 如何准确定位到网络上的一台或者多台主机
- 找到主机之后如何进行通信
- 网络编程中的要素
- ip和端口号 ip
- 网络通信协议 udp,tcp
- 万物皆对象
1.3、IP
ip地址:InetAddress
-
唯一定位一台计算机
-
127.0.01:本机localhost
-
ip地址分类
-
ipv4/ipv6地址分类
- IPV4 127.0.0.1 ,4个字节组成,1个字节8位。0-255,42亿~;30亿都在北美,亚洲4亿,2011年就用尽了。
- IPV6 fe80::e574:5dfc:4204:8875%11,16个字节,128位。8个无符号整数。
2001:0bb2:aaa:0015:0000:0000:1aaa:1312 每个数字都是16进制,一个十六进制数可以写成4个二进制数(就是占4位)。共32个数字*4位=128
-
公网(互联网)-私网(局域网)
-
ABCD类地址
-
192.168.xx.xx ,专门给组织内部使用的。
-
-
-
域名:记忆IP问题!
- IP:www.vip.com 万网
import java.net.UnknownHostException;
public class TestInetAddress {
public static void main(String[] args) {
try {
//查询本地地址
InetAddress byName = InetAddress.getByName("127.0.0.1");
System.out.println(byName);
//查询网站ip地址
InetAddress byName1 = InetAddress.getByName("www.baidu.com");
System.out.println(byName1);
//常用方法
System.out.println(byName1.getAddress());
System.out.println(byName1.getCanonicalHostName());//规范的名字
System.out.println(byName1.getHostAddress());//ip
System.out.println(byName1.getHostName());//域名,或者自己的电脑的额名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
1.4、端口
端口表示计算机上的一个程序的进程。
-
不同进程有不同的端口号!用来区分软件!
-
端口被规定范围:0~65535
-
TCP,UDP:这两个都有65535这么多端口,即65535*2。tcp:80,udp:80.单个协议下,端口号不能冲突。
-
端口分类
-
公有端口0-1023
- HTTP默认端口:80
- HHTPS默认端口:443
- FTP:21
- Telent:23
-
程序注册端口:1024~49151,非陪用户或者程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
-
动态、私有:49152-65535
netstat -ano 命令:可以查看本机开放的全部端口。
- LISTENING时表示处于侦听状态,就是说该端口是开放的,等待连接,但还没有被连接。就像
你房子的门已经敞开的,但还没有人进来。 - ESTABLISHED的意思是建立连接。表示两台机器正在通信。
- CLOSE_WAIT 对方主动关闭连接或者网络 异常导致连接中断。
- TIME_WAIT 我方主动调用close()断开连接,收到对方确认后状态变为TIME_WAIT。
netstat -ano|findstr "5900":查看5900端口详情。 tasklist|findsr "8696" :查看指定端口的进程。(或者电脑任务管理器里面的PID栏查看)
public class TestInetSocktaddress { public static void main(String[] args) { InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8080); InetSocketAddress inetSocketAddress2 = new InetSocketAddress("localhost", 8080); System.out.println(inetSocketAddress); System.out.println(inetSocketAddress2); System.out.println(inetSocketAddress.getAddress()); System.out.println(inetSocketAddress.getHostName());//hosts文件可以配置映射地址 System.out.println(inetSocketAddress.getPort());//端口 } }
- LISTENING时表示处于侦听状态,就是说该端口是开放的,等待连接,但还没有被连接。就像
-
1.5、通信协议
协议:约定,就好比我们现在说的是普通话。
**网络通信协议:**速率,传输码率,代码结构,传输控制。。。
**问题:**非常的复杂
大事化小:分层!
TCP/IP协议簇:实际上是一组协议
重要:
- TCP:用户传输协议。
- UDP:用户数据报协议。
出名的协议:
- TCP:用户传输协议。
- IP:网络互联协议。
TCP和UDP对比:
TCP:打电话
- 连接,稳定
- 三次握手,四次挥手。
最少需要三次,保证稳定连接!
A:你瞅啥?
B:瞅你咋地?
A:干一场!
四次挥手:
A:我要走了
B:你真的要走了吗?
B:你真的真的要走了吗?
A:我真的要走了!
- 客户端,服务端
- 传输完成,释放连接,效率低
UDP:发短信
- 不连接,不稳定。
- 客户端、服务端:没有明确的界限。
- 不管有没有准备好,都可以发给你。
- 导弹攻击
- DDOS:洪水攻击!(饱和攻击)
1.6、TCP
客户端
- 连接服务器 Socket
- 发送消息
//客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
Socket socket=null;
OutputStream outputStream=null;
try {
//1.要知道服务器的地址、端口号
InetAddress serverIp=InetAddress.getByName("127.0.0.1");
int port=9999;
//2.创建一个socket连接
socket = new Socket(serverIp,port);
//3.发送消息 IO流
outputStream = socket.getOutputStream();
outputStream.write("你好,欢迎学习java".getBytes());
} catch (Exception e) {
e.printStackTrace();
}finally {
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务器
- 建立服务端口ServerSocket
- 等待用户的连接accept
- 接收消息
//服务端
public class TcpServerDemo01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
ByteArrayOutputStream baos = null;
try {
//1.我得有一个地址
serverSocket = new ServerSocket(9999);
while (true){
//2.等待客户端连接过来
socket = serverSocket.accept();
//3.读取客户端的消息
inputStream = socket.getInputStream();
//管道流
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件上传
//服务端
public class TcpServerDemo02 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
FileOutputStream baos = null;
OutputStream outputStream = null;
try {
//1.创建服务
serverSocket = new ServerSocket(9000);
//2.监听客户端连接//阻塞式监听,会一直等待客户端连接
socket = serverSocket.accept();
//3.读取客户端的消息//获取输入流
inputStream = socket.getInputStream();
//4.文件输出,利用管道流
baos = new FileOutputStream(new File("jyw123.jpg"));
byte[] buffer = new byte[1024];
int len;
//每次读取一个字节
while ((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
//通知客户端接收完毕
outputStream = socket.getOutputStream();
outputStream.write("我接受完毕了,你可以断开了".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
//客户端
public class TcpClientDemo02 {
public static void main(String[] args) {
//1。创建一个Socket连接
Socket socket = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
//2.创建一个输出流
OutputStream outputStream = socket.getOutputStream();
//3.文件流
FileInputStream fileInputStream = new FileInputStream(new File("F:\\worksapce\\wlbc-study\\src\\123.jpg"));
//4.写出文件
byte[] buffer = new byte[1024];
int len;
// read (byte[] b) 方法, 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。
while ((len=fileInputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
//通知服务器,我已经结束了
socket.shutdownOutput();//我已经传输完了
//确定服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
//String byte[]
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());
//5.关闭资源
baos.close();
fileInputStream.close();
outputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Tomcat
服务端
- 自定义S
- Tomcat服务器S
客户端
- 自定义 C
- 浏览器 B
1.7、UDP
发短信:不用连接,需要知道对方的地址!
发送消息:
public class UdpClientDemo1 {
public static void main(String[] args) throws Exception {
//1.建立一个Socket
DatagramSocket socket = new DatagramSocket();
//2.建立包
String msg = "你好,服务器";
//发送给谁
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
//下面的参数解释:数据,数据长度起始,要发送给谁
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
//3.发送包
socket.send(packet);
//4.关闭资源
socket.close();
}
}
接收消息
//还是要等待客户端的连接!
public class UdpServerDemo1 {
public static void main(String[] args) throws Exception {
//开放端口
DatagramSocket socket = new DatagramSocket(9090);
//接收数据包
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();
}
}
循环发送消息
public class UdpSendDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
//准备数据:读取控制台Ststem.in
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String data = reader.readLine();
byte[] dates = data.getBytes();
DatagramPacket packet = new DatagramPacket(dates, 0, dates.length, new InetSocketAddress("localhost", 6666));
System.out.println(dates.length);//bye:3
System.out.println(packet.getLength());//bye:3
socket.send(packet);
if (data.equals("bye")) {
break;
}
}
socket.close();
}
}
循环接收消息
public class UdpReceiveDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true) {
//准备接收包裹,放到container里面
byte[] container = new byte[1024];
System.out.println(container.length);//1024
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
System.out.println(packet.getLength());//1024
socket.receive(packet);//阻塞式接收包裹。上面是1024,下面是3,说明receive方法将他改变了
System.out.println(packet.getLength());//3
//断开连接byte
byte[] data = packet.getData();//1024
//String receiveData = new String(data, 0, data.length);//1024
String receiveData = new String(data, 0, packet.getLength());
//我不需要固定数组container那么长(1024),我只需要packet里面数据长度(3),这样写后面的equals判断不需要写trim()
System.out.println(packet.getLength());//收到的是长度是3
System.out.println(data.length);//1024
System.out.println(receiveData.length());//3
System.out.println(receiveData);
if (receiveData.trim().equals("bye")) {
break;
}
}
socket.close();
}
}
在线咨询:两个人都可以发送方,也都可以是接收方!
多线程互相聊天
发送类工具
//发送线程
public class TalkSend implements Runnable{
DatagramSocket socket =null;
BufferedReader reader =null;
private String toIp;
private int fromPort;
private int toPort;
public TalkSend(int fromPort,String toIp, int toPort) {
this.toIp = toIp;
this.fromPort = fromPort;
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();
DatagramPacket packet = new DatagramPacket(data.getBytes(), 0, data.getBytes().length, new InetSocketAddress(this.toIp, this.toPort));
socket.send(packet);
if (data.equals("bye")) {
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}
接受类工具
//接收线程
public class TalkReceive implements Runnable{
DatagramSocket socket =null;
private int port;
private String msgFrom;//消息来源
public TalkReceive(int port,String msgFrom) {
this.port = port;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
//准备接收包裹,放到container里面
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet);//阻塞式接收包裹。上面是1024,下面是3,说明receive方法将他改变了
//断开连接byte
String receiveData = new String(packet.getData(), 0, packet.getLength());
System.out.println(msgFrom+":"+receiveData);
if (receiveData.trim().equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
学生端启动类
public class TalkStudent {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(7777,"localhost",9999)).start();
new Thread(new TalkReceive(8888,"老师")).start();
}
}
老师类启动端
public class TalkTeacher {
public static void main(String[] args) {
//开启两个线程
new Thread(new TalkSend(5555,"localhost",8888)).start();
new Thread(new TalkReceive(9999,"学生")).start();
}
}
1.8、URL
https://www.baidu.com/
统一资源定位符:定位资源,定位互联网上的某一资源。
DNS域名解析:将https://www.baidu.com/解析成xxx.x…x…x
本质是把域名解析成ip
基本上5部分组成:
协议://IP地址:端口/项目名/对应资源
public class URLDown {
public static void main(String[] args) throws Exception {
//1.下载地址
URL url = new URL("https://m10.music.126.net/20200919161055/7963703b1af08b9d00a2e6ce2ba6c981/yyaac/obj/wonDkMOGw6XDiTHCmMOi/3918591949/c8a1/cba7/c6ea/5a3677569928db9f736580e5a2107f55.m4a");
HttpsURLConnection httpURLConnection=(HttpsURLConnection)url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("f.m4a");
byte[] bytes = new byte[1024];
int len;
if ((len=inputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,len);//写出这个数据
}
fileOutputStream.close();
inputStream.close();
httpURLConnection.disconnect();//断开连接
}
}