文章目录
网络编程
1.1概述
计算机网络:
计算机网络是指将==地理位置==不同的计算机及其外部部件,通过通信线路连接起来,在网络编程协议下,实现不同计算机之间的信息共享以及信息交流的计算机系统。
网络编程的目的:
传播交流信息(无线电台):数据交换,通信。
想要达到这些效果需要做什么:
- 如何准确地定位网络上的一台主机 192.168.16.124:端口,定位到这个计算机上的某个资源
- 找到了这个主机,如何传输数据呢?
javaweb:网页编程 B/S
网络编程:TCP/IP C/S
1.2 网络通信的要素
TCP/IP参考模型:
网络编程针对传输层 TCP,UDP
小结:
- 网络编程两个主要问题
- 如何准确定位到网络上的一台或多台主机
- 找到主机之后如何进行通信
- 网络编程中的要素
- IP和端口号
- 网络通信协议:TCP,UDP
- 万物皆对象
1.3 IP地址
ip地址:InterAddress
-
唯一定位一台网络上的计算机
-
127.0.0.1:本机,localhost(C:\Windows\System32\drivers\etc\hosts 可以更改名称)
-
ip地址分类
-
IPv4 / IPv6
-
==IPV4:==127.0.0.1,四个字节组成。0 ~ 255, 42亿~;30亿都在北美,亚洲4亿。2001年就用尽了;
-
==IPV6:==fe80::755f:fc6c:2ebc:b6e6%18,128位。8个无符号整数!可以给地球上每粒沙子分配;
-
2001:0bb2:aaaa:0015:0000:0000:1aaa:1312
-
-
公网(互联网) / 私网(局域网)
- ABCD类地址
- 192.168.xx.xx,专门给组织内部使用
-
- 域名:记忆IP问题
- IP:www.vip.com
练习:InetAddress类的常用方法
package com.sw.lesson01;
import java.net.InetAddress;
import java.net.UnknownHostException;
//测试IP
public class Test01 {
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 localHost = InetAddress.getLocalHost();
System.out.println(localHost);
//查询网站IP地址
InetAddress inetAddress3 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress3);
System.out.println("=======================");
//常用方法
// System.out.println(inetAddress3.getAddress()); //返回原生地址,没什么用
System.out.println(inetAddress3.getCanonicalHostName()); //规范的名字
System.out.println(inetAddress3.getHostAddress()); //ip地址(常用)
System.out.println(inetAddress3.getHostName()); //域名,或者自己电脑的名字
System.out.println(inetAddress2.getHostName()); //自己电脑的名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
1.4 端口
端口表示计算机上的一个程序的进程;
- 不同的进程有不同的端口号!用来区分软件!
- 被规定0 ~ 65535(电脑最多跑的进程数)
- TCP,UDP:65535 * 2 ,单个协议下,端口号不能冲突(tcp:80 udp:80可以)
分类:
-
公有端口 0~1023
- HTTP:80
- HTTPS:443
- FTP:21
- Telent:23
-
程序注册端口:1024~49151,分配给用户或者程序
- Tomcat:8080
- MySQL:3306
- Oracle:1521
-
动态、私有:49152~65535
cmd常用命令: netstat -ano #查看所有的端口 netstat -ano | findstr "5900" #查看指定的端口 tasklist | findstr "8696" #查看指定端口的进程 ctrl + shift + ESC #打开任务管理器,死机也能用
练习:InetSocketAddress类
package com.sw.lesson01; import java.net.InetSocketAddress; //练习 InetSocketAddress类 public class Test02 { public static void main(String[] args) { InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 8080); InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080); System.out.println(socketAddress1); // /127.0.0.1:8080 System.out.println(socketAddress2); // localhost/127.0.0.1:8080 System.out.println(socketAddress1.getAddress()); //IP地址 /127.0.0.1 System.out.println(socketAddress1.getHostName()); //activate.navicat.com System.out.println(socketAddress1.getPort()); //端口号 8080 } }
1.5 通讯协议
协议:约定,就好比我们现在说的是普通话。
**网络通信协议:**速率,传输码率,传输控制……
**问题:**非常的复杂?
大事化小:分层!
TCP/IP协议簇:
重要的两个协议:
- TCP:用户传输协议
- UDP:用户数据报协议
出名的协议:TCP,IP(网络互连协议),实际上是一组协议
TCP,UDP对比:
-
TCP:打电话
- 连接:稳定
- 三次握手 四次挥手
- 客户端,服务端
- 传输完成,释放连接、效率低
-
UDP:发短信
- 连接:不稳定
- 客户端,服务端没有明显的界限
- 不管有没有准备好,都可以发给你(导弹)
- DDOS:洪水攻击!饱和攻击
TCP和UDP的区别
-
TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
-
TCP要求的系统资源较多,UDP较少
-
TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
-
TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
-
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
-
TCP首部开销20字节;UDP的首部开销小,只有8个字节
-
TCP的逻辑通信信道是全双工的可靠信道;UDP则是不可靠信道
扩展:三次握手,四次挥手
最少需要三次,保证稳定连接
A:你瞅啥? #第一次握手:客户端向服务端申请连接
B:瞅你咋地? #第二次握手:服务端向客户端返回确认同意连接
A:干一场! #第三次握手:客户端发送确认报文段,完成连接
A:我要走了
B:你真的要走了吗?
B:你真的真的要走了吗?
A:我真的要走了
TCP三次握手
1.“三次握手”的通俗理解
举个栗子:把客户端比作男孩,服务器比作女孩。用他们的交往来说明“三次握手”过程:
(1)男孩喜欢女孩,于是写了一封信告诉女孩:我爱你,请和我交往吧!;写完信之后,男孩焦急地等待,因为不知道信能否顺利传达给女孩。
(2)女孩收到男孩的情书后,心花怒放,原来我们是两情相悦呀!于是给男孩写了一封回信:我收到你的情书了,也明白了你的心意,其实,我也喜欢你!我愿意和你交往!;
写完信之后,女孩也焦急地等待,因为不知道回信能否能顺利传达给男孩。
(3)男孩收到回信之后很开心,因为发出的情书女孩收到了,并且从回信中知道了女孩喜欢自己,并且愿意和自己交往。然后男孩又写了一封信告诉女孩:你的心意和信我都收到了,谢谢你,还有我爱你!
女孩收到男孩的回信之后,也很开心,因为发出的情书男孩收到了。由此男孩女孩双方都知道了彼此的心意,之后就快乐地交流起来了~~
这就是通俗版的“三次握手”,期间一共往来了三封信也就是“三次握手”,以此确认两个方向上的数据传输通道是否正常。
2.为什么要进行第三次握手
为了防止服务器端开启一些无用的连接增加服务器开销以及防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
由于网络传输是有延时的(要通过网络光纤和各种中间代理服务器),在传输的过程中,比如客户端发起了SYN=1创建连接的请求(第一次握手)。
如果服务器端就直接创建了这个连接并返回包含SYN、ACK和Seq等内容的数据包给客户端,这个数据包因为网络传输的原因丢失了,丢失之后客户端就一直没有接收到服务器返回的数据包。
客户端可能设置了一个超时时间,时间到了就关闭了连接创建的请求。再重新发出创建连接的请求,而服务器端是不知道的,如果没有第三次握手告诉服务器端客户端收的到服务器端传输的数据的话,
服务器端是不知道客户端有没有接收到服务器端返回的信息的。
这个过程可理解为:
这样没有给服务器端一个创建还是关闭连接端口的请求,服务器端的端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。那么服务器端上没有接收到请求数据的上一个端口就一直开着,长此以往,这样的端口多了,就会造成服务器端开销的严重浪费。
还有一种情况是已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。
所以我们需要“第三次握手”来确认这个过程,让客户端和服务器端能够及时地察觉到因为网络等一些问题导致的连接创建失败,这样服务器端的端口就可以关闭了不用一直等待。
也可以这样理解:“第三次握手”是客户端向服务器端发送数据,这个数据就是要告诉服务器,客户端有没有收到服务器“第二次握手”时传过去的数据。若发送的这个数据是“收到了”的信息,接收后服务器就正常建立TCP连接,否则建立TCP连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。
TCP的四次挥手
“四次挥手”的通俗理解
举个栗子:把客户端比作男孩,服务器比作女孩。通过他们的分手来说明“四次挥手”过程。
- “第一次挥手”:日久见人心,男孩发现女孩变成了自己讨厌的样子,忍无可忍,于是决定分手,随即写了一封信告诉女孩。
- “第二次挥手”:女孩收到信之后,知道了男孩要和自己分手,怒火中烧,心中暗骂:你算什么东西,当初你可不是这个样子的!于是立马给男孩写了一封回信:分手就分手,给我点时间,我要把你的东西整理好,全部还给你!
男孩收到女孩的第一封信之后,明白了女孩知道自己要和她分手。随后等待女孩把自己的东西收拾好。 - “第三次挥手”:过了几天,女孩把男孩送的东西都整理好了,于是再次写信给男孩:你的东西我整理好了,快把它们拿走,从此你我恩断义绝!
- “第四次挥手”:男孩收到女孩第二封信之后,知道了女孩收拾好东西了,可以正式分手了,于是再次写信告诉女孩:我知道了,这就去拿回来!
这里双方都有各自的坚持
女孩自发出第二封信开始,限定一天内收不到男孩回信,就会再发一封信催促男孩来取东西!
男孩自发出第二封信开始,限定两天内没有再次收到女孩的信就认为,女孩收到了自己的第二封信;
若两天内再次收到女孩的来信,就认为自己的第二封信女孩没收到,需要再写一封信,再等两天…..
倘若双方信都能正常收到,最少只用四封信就能彻底分手!这就是“四次挥手”。
为什么“握手”是三次,“挥手”却要四次?
TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。
即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。
TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?
建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,
开始建立连接。
释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,
因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,
才能返回FIN释放连接报文。
所以是“三次握手”,“四次挥手”。
1.6 TCP协议
利用Socket进行传输
1.TCP实现聊天
客户端:
- 连接服务器 Socket(address,port)
- 发送消息
服务器:
- 建立服务的端口 ServerSocket
- 等待用户的连接 accept()
- 接收用户的消息
过程:
1.客户端要和服务端建立连接,所以就需要知道服务端的IP地址和端口号,所以服务端就要有一个IP地址和端口号,所以就在服务端创建一个(因为是在本机,所以IP地址为本机地址,只需要创建一个端口号)
//服务端创建端口号
ServerSocket serverSocket = new ServerSocket(9999);
2.建立连接
客户端请求与服务端建立连接,服务端等待客户端连接
// 客户端请求与服务端建立连接
Socket socket = new Socket("127.0.0.1", 9999);
//服务端等待客户端连接
Socket socket = serverSocket.accept();
3.连接成功,发送消息(IO流)
客户端发送消息(写数据),服务端接收消息(读数据)
//客户端发送消息(写数据)
OutputStream os = socket.getOutputStream();
os.write("你好,我是某某某".getBytes());
//服务端接收消息(读数据)
InputStream is = socket.getInputStream();
/*
//普通读取
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1){
System.out.println(new String(bytes,0,len));
}
*/
//管道流读取(过滤一下,防止中文乱码)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1){
baos.write(bytes,0,len);
}
System.out.println(baos.toString());
TCP实现聊天代码:
客户端:
package com.sw.lesson02;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
//TCP实现聊天客户端
public class TcpClientDemo01 {
public static void main(String[] args) {
OutputStream os = null;
Socket socket = null;
try {
//1.要知道服务器端的地址,端口号
// InetAddress serverIP = InetAddress.getByName("127.0.0.1");
// int port = 9999;
//2.创建一个socket连接
// socket = new Socket(serverIP, port);
//请求建立连接
socket = new Socket("127.0.0.1", 9999);
//3.用Socket连接发送消息 IO流
os = socket.getOutputStream();
os.write("你好,我是某某某".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();
}
}
}
}
}
服务端:
package com.sw.lesson02;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//TCP实现聊天服务端
public class TcpServerDemo01 {
public static void main(String[] args) {
ByteArrayOutputStream baos = null;
InputStream is = null;
Socket socket = null;
ServerSocket serverSocket = null;
try {
//1.我得有一个地址 创建服务器端口
serverSocket = new ServerSocket(9999);
while (true){
//2.用Socket连接等待客户端连接过来(监听用户的连接)
socket = serverSocket.accept();
//读取客户端的消息
is = socket.getInputStream();
//普通读取
// byte[] bytes = new byte[1024];
// int len;
// while ((len = is.read(bytes)) != -1){
// System.out.println(new String(bytes,0,len));
// }
//管道流读取(过滤一下,防止中文乱码)
baos = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1){
baos.write(bytes,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 (is != null){
try {
is.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();
}
}
}
}
}
2.TCP文件上传实现
过程:
1.客户端要和服务端建立连接,所以就需要知道服务端的IP地址和端口号,所以服务端就要有一个IP地址和端口号,所以就在服务端创建一个(因为是在本机,所以IP地址为本机地址,只需要创建一个端口号)
//创建服务
ServerSocket serverSocket = new ServerSocket(9999);
2.客户端请求与服务端建立连接,服务端等待客户端连接
//客户端请求与服务端建立连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
//服务端等待客户端连接(监听用户的连接)
Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端的连接
3.建立成功,客户端发送文件,并通知服务端自己传输完成
//上传文件
//1.把文件读出来变成流
//2.把流发过去(写)
OutputStream outputStream = socket.getOutputStream();
//1.把文件读出来变成流
FileInputStream fileInputStream = new FileInputStream("F:\\python\\io_test\\picture.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = fileInputStream.read(bytes)) != -1){
//2.用Socket连接把流发过去(写)
outputStream.write(bytes,0,len);
}
//通知服务器,我已经传输完了
socket.shutdownOutput();
4.服务端接收文件,并通知客户端接收完毕,然后关闭资源
//用Socket连接接收文件
//1.把传输过来的流接收(读)
//2.把流写出来
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("NetWork\\src\\com\\sw\\lesson02\\picture.jpg");
//1.把传输过来的流接收(读)
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,len);
}
//通知客户端接收完毕了
OutputStream outputStream = socket.getOutputStream();
outputStream.write("我接收完毕了,你可以断开了".getBytes());
//关闭资源
fileOutputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
5.客户端确认服务端接收完毕之后断开连接
//确定服务端接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
//普通
// byte[] bytes1 = new byte[1024];
// int len1;
// while ((len1 = inputStream.read(bytes1)) != -1){
// System.out.println(new String(bytes1,0,len1));
// }
//管道流
//客户端发过来一个字节数组,所以需要管道流过滤
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes1 = new byte[1024];
int len1;
while ((len1 = inputStream.read(bytes1)) != -1){
baos.write(bytes1,0,len1);
}
System.out.println(baos.toString());
//3.关闭资源
fileInputStream.close();
outputStream.close();
socket.close();
TCP实现文件上传代码==:==
客户端
package com.sw.lesson02;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
//TCP文件上传客户端
public class TcpClientDemo02 {
public static void main(String[] args) throws Exception {
//客户端请求与服务端建立连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
//上传文件
//1.把文件读出来变成流
//2.把流发过去(写)
OutputStream outputStream = socket.getOutputStream();
//1.把文件读出来变成流
FileInputStream fileInputStream = new FileInputStream("F:\\python\\io_test\\picture.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = fileInputStream.read(bytes)) != -1){
//2.用Socket连接把流发过去(写)
outputStream.write(bytes,0,len);
}
//通知服务器,我已经传输完了
socket.shutdownOutput();
//确定服务端接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
//普通
// byte[] bytes1 = new byte[1024];
// int len1;
// while ((len1 = inputStream.read(bytes1)) != -1){
// System.out.println(new String(bytes1,0,len1));
// }
//管道流
//客户端发过来一个字节数组,所以需要管道流过滤
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes1 = new byte[1024];
int len1;
while ((len1 = inputStream.read(bytes1)) != -1){
baos.write(bytes1,0,len1);
}
System.out.println(baos.toString());
//3.关闭资源
fileInputStream.close();
outputStream.close();
socket.close();
}
}
服务端:
package com.sw.lesson02;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//TCP文件上传服务端
public class TcpServerDemo02 {
public static void main(String[] args) throws Exception {
//创建服务
ServerSocket serverSocket = new ServerSocket(9999);
//服务端等待客户端连接(监听用户的连接)
Socket socket = serverSocket.accept();//阻塞式监听,会一直等待客户端的连接
//用Socket连接接收文件
//1.把传输过来的流接收(读)
//2.把流写出来
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("NetWork\\src\\com\\sw\\lesson02\\picture.jpg");
//1.把传输过来的流接收(读)
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,len);
}
//通知客户端接收完毕了
OutputStream outputStream = socket.getOutputStream();
outputStream.write("我接收完毕了,你可以断开了".getBytes());
//关闭资源
fileOutputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
初识Tomcat
服务端:
- 自定义 C
- Tomcat服务器 S:Java后端开发
客户端:
- 自定义 C
- 浏览器 B
1.7 UDP
数据报包(DatagramSocket)发送与接收
利用DatagramSocket进行传输
1.UDP消息发送
过程:
1.发送方要给接收方发送消息,就需要知道接收方的信息,所以接收方就需要开放一个端口给发送方
//1.接收方开放端口
DatagramSocket datagramSocket = new DatagramSocket(6666);
2.发送方给接收方发送消息,就需要发送消息的数据报的套接字的send方法,该方法需要一个存放消息的数据报包,所以就创建一个数据报包来存放消息,发送完成关闭资源。
//2.建个包
//包里面的数据和信息
String s = "你好啊,服务器";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 6666;
//参数(数据(字节数组),数据开始位置,数据数组长度,IP地址,端口号)
DatagramPacket packet = new DatagramPacket(s.getBytes(),0,s.getBytes().length,localhost,port);
//3.发送包
datagramSocket.send(packet);
//4.关闭资源
datagramSocket.close();
3.接收方接收数据,接收方也需要,一个数据报包来接收数据,并用接收方的数据报套接字的receive方法来接收并输出,接收完成关闭资源
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
datagramSocket.receive(packet); //阻塞接收
//3.输出消息
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
//4.关闭连接
datagramSocket.close();
UDP消息发送代码
发送方:
package com.sw.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//UDP不需要连接服务器
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception{
//1.建立一个Socket
DatagramSocket datagramSocket = new DatagramSocket();
//2.建个包
//包里面的数据和信息
String s = "你好啊,服务器";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 6666;
//参数(数据(字节数组),数据开始位置,数据数组长度,IP地址,端口号)
DatagramPacket packet = new DatagramPacket(s.getBytes(),0,s.getBytes().length,localhost,port);
//3.发送包
datagramSocket.send(packet);
//4.关闭资源
datagramSocket.close();
}
}
接收方:
package com.sw.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
//还是要等待客户端的连接
public class UdpServerDemo01 {
public static void main(String[] args) throws Exception {
//1.开放端口,建立连接
DatagramSocket datagramSocket = new DatagramSocket(6666);
//2.接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
datagramSocket.receive(packet); //阻塞接收
//3.输出消息
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(),0,packet.getLength()));
//4.关闭连接
datagramSocket.close();
}
}
2.UDP聊天实现(循环发送,循环接收)
UDP聊天实现(循环发送,循环接收)代码
发送方:
package com.sw.udp.chat;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//发送方
public class UdpSenderDemo01 {
public static void main(String[] args) throws Exception {
//建立连接,自己也开发端口用来接收消息
DatagramSocket datagramSocket = new DatagramSocket(8888);
//数据包:控制台读取
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));;
//循环发送
while (true) {
String s = br.readLine();
DatagramPacket packet = new DatagramPacket(s.getBytes(),0,s.getBytes().length, InetAddress.getByName("localhost"),7777);
//发送数据
datagramSocket.send(packet);
//结束条件
if (s.equals("再见")){
break;
}
}
//关闭资源
br.close();
datagramSocket.close();
}
}
接收方:
package com.sw.udp.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
//接收方
public class UdpReceiveDemo01 {
public static void main(String[] args) throws Exception {
//开放端口
DatagramSocket datagramSocket = new DatagramSocket(7777);
//循环接收
while (true) {
//创建接收数据的包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
//接收数据
datagramSocket.receive(packet);
//输出数据
// String s = new String(bytes, 0, packet.getLength(),"gbk"); //和黑窗口对话
String s = new String(bytes, 0, packet.getLength());
System.out.println(s);
//结束条件
if (s.equals("再见")){
break;
}
}
//关闭资源
datagramSocket.close();
}
}
3.多线程实现在线咨询
代码:
发送方:
package com.sw.udp.superChat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
public class TalkSend implements Runnable{
DatagramSocket datagramSocket = null;
BufferedReader br = null;
// private int fromPort;
private String toIP;
private int toPort;
public TalkSend(String toIP,int toPort) {
// this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;
try {
datagramSocket = new DatagramSocket();
br = new BufferedReader(new InputStreamReader(System.in,"GBK"));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
//循环发送
try {
while (true) {
String s = br.readLine();
DatagramPacket packet = new DatagramPacket(s.getBytes(),0,s.getBytes().length, InetAddress.getByName(this.toIP),this.toPort);
// DatagramPacket packet = new DatagramPacket(s.getBytes(),0,s.getBytes().length, new InetSocketAddress(this.toIP,this.toPort));
//发送数据
datagramSocket.send(packet);
//结束条件
if (s.equals("再见")){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
datagramSocket.close();
}
}
}
接收方:
package com.sw.udp.superChat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class TalkReceive implements Runnable{
DatagramSocket datagramSocket = null;
private int myPort;
private String msgFrom;
public TalkReceive(int myPort,String msgFrom) {
this.myPort = myPort;
this.msgFrom = msgFrom;
try {
datagramSocket = new DatagramSocket(myPort);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true) {
//创建接收数据的包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
//接收数据
datagramSocket.receive(packet);
//输出数据
// String s = new String(bytes, 0, packet.getLength(),"gbk"); //用GBK输出
String s = new String(bytes, 0, packet.getLength());
System.out.println(this.msgFrom + ":" + s);
//结束条件
if (s.equals("再见")){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
datagramSocket.close();
}
}
}
聊天人员A:
package com.sw.udp.superChat;
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend("localhost",8888)).start();
new Thread(new TalkReceive(6666,"老师")).start();
}
}
聊天人员B:
package com.sw.udp.superChat;
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend("localhost",6666)).start();
new Thread(new TalkReceive(8888,"学生")).start();
}
}
1.8 URL
www.baidu.com
统一资源定位符:定位资源的,定位互联网上的某一个资源
DNS域名解析 www.baidu.com xxx.x.xx.xx
http://localhost:8080/xxx/xxx
https://blog.csdn.net/fllow_wind/article/details/117029719?spm=1001.2014.3001.5502
协议://ip地址:端口/项目名/资源
package com.sw.url;
import java.net.MalformedURLException;
import java.net.URL;
//测试URL
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("https://blog.csdn.net/fllow_wind/article/details/117029719?spm=1001.2014.3001.5502");
System.out.println("getProtocol :" + url.getProtocol()); //协议
System.out.println("getHost: " + url.getHost()); //主机IP
System.out.println("getPort: " + url.getPort()); //端口
System.out.println("getPath: " + url.getPath()); //文件
System.out.println("getFile: " + url.getFile()); //全路径
System.out.println("getQuery: " + url.getQuery()); //参数
/*
getProtocol :https
getHost: blog.csdn.net
getPort: -1
getPath: /fllow_wind/article/details/117029719
getFile: /fllow_wind/article/details/117029719?spm=1001.2014.3001.5502
getQuery: spm=1001.2014.3001.5502
*/
}
}
下载文件
package com.sw.url;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
//下载文件
public class URLDown {
public static void main(String[] args) throws Exception {
//1.下载地址
URL url = new URL("https://cn.bing.com/images/search?view=detailV2&ccid=nfC2tVNM&id=49E031AAC7715C25D8E03215367A7B4A50E14354&thid=OIP.nfC2tVNM9TgwQ5QuqECd6wHaFj&mediaurl=https%3a%2f%2fimg.mianfeiwendang.com%2fpic%2f65133e4129b6446aa22c9f9f%2f1-810-jpg_6-1080-0-0-1080.jpg&exph=810&expw=1080&q=%e5%9b%be%e7%89%87&simid=608035324947293979&FORM=IRPRST&ck=80CEE6C1EA35720EF9BEBABB8A76BE85&selectedIndex=0");
//2.连接到这个资源HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//3.把这个资源变成流,也就是读数据
InputStream inputStream = urlConnection.getInputStream();
//下载到哪里,也就是写数据
FileOutputStream fileOutputStream = new FileOutputStream("NetWork\\src\\com\\sw\\url\\picture.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,len);
}
//关闭资源
fileOutputStream.close();
inputStream.close();
urlConnection.disconnect(); //断开连接
}
}
import java.net.URLConnection;
//下载文件
public class URLDown {
public static void main(String[] args) throws Exception {
//1.下载地址
URL url = new URL(“https://cn.bing.com/images/search?view=detailV2&ccid=nfC2tVNM&id=49E031AAC7715C25D8E03215367A7B4A50E14354&thid=OIP.nfC2tVNM9TgwQ5QuqECd6wHaFj&mediaurl=https%3a%2f%2fimg.mianfeiwendang.com%2fpic%2f65133e4129b6446aa22c9f9f%2f1-810-jpg_6-1080-0-0-1080.jpg&exph=810&expw=1080&q=%e5%9b%be%e7%89%87&simid=608035324947293979&FORM=IRPRST&ck=80CEE6C1EA35720EF9BEBABB8A76BE85&selectedIndex=0”);
//2.连接到这个资源HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//3.把这个资源变成流,也就是读数据
InputStream inputStream = urlConnection.getInputStream();
//下载到哪里,也就是写数据
FileOutputStream fileOutputStream = new FileOutputStream("NetWork\\src\\com\\sw\\url\\picture.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,len);
}
//关闭资源
fileOutputStream.close();
inputStream.close();
urlConnection.disconnect(); //断开连接
}
}