网络编程
概述
首先理解TCP和UDP的区别
TCP:打电话:--连接--接了--通话--
计算机网络
计算机网络是指将==地理位置不同==的具有独立功能的==多台计算机及外部设备,通过通信线路连接起来==,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
网络编程的目的:
-
-
数据交换--通信
想要达到的这个效果需要什么:
1、如何准确的定位网络上的一台主机,198.168.1.1。通过计算机的端口定位到这个计算机的某个资源。
通过硬件用于传输数据
网络编程:TCP/IP C/S,全程为Client/Server结构,是指客户端和服务器结构。
如果实现网络通信?
通信双方地址:
-
IP
-
端口号
规则:就是网络通信的协议
TCP/IP参考模型

小结:网络编程中的两个主要问题?
-
如何准确定位到网络上的一台或多台主机?(用ping + 网址)
-
网络编程中的要素
-
IP和端口号 IP
-
万物皆对象
IP地址
API文档的方法:InetAddress
IPV4:127.0.0.1,4个字节组成。0~255,大约42亿;30亿在北美,4亿在亚洲,于2011年用尽了。
IPV6:128位,8个无符号整数!据说可以把地球的每粒沙子都标有地址
fe80::b442:9d87:5428:8ee8%11
公网(互联网)-私网(局域网)
ABCD类地址
192.168.x.x,专门用于组织内部使用
域名:记忆IP
例如:
//测试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);
//常用的方法
//返回此对象InetAddress的原始地址
System.out.println(inetAddress2.getAddress());
//获取此IP地址的限定域名--获取规范的名字
System.out.println(inetAddress2.getCanonicalHostName());
//返回文本显示中的IP地址字符串
System.out.println(inetAddress2.getHostAddress());
//获取此IP地址的主机名。
System.out.println(inetAddress2.getHostName());
//UnknownHostException表示
// 这个问题的出现是由于你的IP地址名称找不到对应的ip地址,
// 就如同你在本地启动程序时默认为“localhost”。
}catch (UnknownHostException e){
e.printStackTrace();
}
}
}
端口
端口表示计算机的一个程序的进程;
不同的进程有不同的端口号!用于区分软件
被规定0-65535
-
TCP,UDP:65535*2,意思是,tcp 80和udp 80端口号不冲突,在单个协议下,端口号可以冲突
端口分类
公有端口0-1023
-
HTTP:80
-
HTTPS:443
-
FTP:21
-
Telent:23
程序注册端口:1023-49151,分配用户或者程序
-
Tomcat:8080
-
MySQL:3306
-
Oracle:1521
动态、私有:49152-65535
netstat -ano #查看所有端口
netstat -ano|findstr "5900"#查看指定的端口
tasklist|findstr"8998" #查看端口的进程
协议:约定,就好比我们现在说的是普通话
网络通信协议:速率,传输码率,代码结构,传输控制
为了能够简化和统一
TCP、IP协议簇:实际上是一组协议
TCP:用户传输协议
UDP:用户数据报协议
出名的协议:

TCP 、UDP的对比
-
TCP:打电话
-
连接、稳定
-
(面试重点)
三次握手:https://www.cnblogs.com/bj-mr-li/p/11106390.html
四次挥手:https://blog.csdn.net/brook_/article/details/81090081
UDP:发短信
-
-
客户端、服务端:没有明确的界限
-
只管发送,不确定对方是否收到
-
例如DDOS:洪水攻击!
理解Tcp上传文件中
客户端:
-
创建一个socket连接
-
创建一个输出流
-
读取文件
-
写出文件
-
通知服务器,已经结束
-
确认服务器接收完毕,才能断开连接
-
关闭资源
public class TcpClinentDemo02 {
public static void main(String[] args) throws Exception{
//1、创建一个Socket连接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
//2、创建一个输出流
OutputStream os = socket.getOutputStream();
//3、读取文件
FileInputStream fis = new FileInputStream("life.png");
//4、写出文件
byte[] buffer = new byte[1024];
int len;
if ((len=fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
//通知服务器,我已经结束
socket.shutdownOutput();
//确定服务器接收完毕,才能断开连接
InputStream inputStream = socket.getInputStream();
//String byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
if ((len2=inputStream.read(buffer2))!=-1){
baos.write(buffer2,0,len2);
}
System.out.println(baos.toString());
//5、关闭资源
os.close();
fis.close();
socket.close();
}
}
服务端:
-
创建服务
-
监听客户端的连接
-
-
文件输出
-
关闭资源
public class TcpServerDemo02 {
public static void main(String[] args) throws Exception{
//1、创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//2、监听客户端的连接
//阻塞式监听,一直等待客户端传递消息
Socket socket = serverSocket.accept();
//3、获取输入流
InputStream is = socket.getInputStream();
//4、文件输出
FileOutputStream fos = new FileOutputStream("out.png");
byte[] buffer = new byte[1024];
int len;
if ((len=is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
//通知客户端我接收完毕了
OutputStream os = socket.getOutputStream();
os.write("已经接收完毕".getBytes());
//5、关闭资源
socket.close();
is.close();
fos.close();
serverSocket.close();
}
}
学会安装tomcat
安装官网:https://tomcat.apache.org/download-80.cgi
如何修改tomcat启动后的乱码

Tomcat闪退
Udp消息发送
理解Udp发送消息后
客户端和服务端的流程
Udp就好比发短信,不用连接,但是需要对方的地址
理解DatagramSocket和DatagramPacket的两者区别
DatagramSocket就好比一个海上运输的轮、DatagramPacket就好比码头
客户端:
结合源码的描述
public DatagramPacket(byte buf[], int offset, int length,
InetAddress address, int port) {
setData(buf, offset, length);
setAddress(address);
setPort(port);
}
-
创建DatagramSocket的端口号;
-
创建DatagramPacket需要的数据、长度、地址、端口;
-
使用DatagramSocket发送socket.send();
-
关闭流socket.close();
-
//不需要连接服务器
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception {
//建议一个连接通道Socket
DatagramSocket socket = new DatagramSocket();
//包的内容
String msg = "apple";
//地址
InetAddress inetAddress = InetAddress.getByName("localhost");
//端口:接收方的端口,发送方可写可不写
int port = 9998;
//建立包
DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,inetAddress,9998);
//发送包
socket.send(datagramPacket);
//关闭流
socket.close();
}
}
服务端:
建立一个DatagramSocket的端口
创建DatagramPacket,接收所需要的数据、长度
使用DatagramSocket的阻塞接收receive用来接收Packet
关闭DatagramSocket
阻塞接收:
receive()方法会使调用线程阻塞。
Java使用DatagramSocket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,它的唯一作用就是接收和发送数据报,Java使用DatagramPacket来代表数据报,DatagramSocket接收和发送的数据都是通过DatagramPacket对象完成的。
public class UdpServerDemo01 {
public static void main(String[] args) throws Exception{
//开放端口
DatagramSocket datagramSocket = new DatagramSocket(9998);
//使用数组接收包的内容
byte[] bytes = new byte[1024];
//接收包
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
//阻塞接收:指的就是
datagramSocket.receive(datagramPacket);
System.out.println(datagramPacket.getAddress().getHostAddress());
System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));
//关闭流
datagramSocket.close();
}
}
Udp实现聊天
理解Udp实现聊天的工作流程
实现聊天的两个关键点
-
-
使用BufferedReader可以输入信息

public class UdpSenderDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket datagramSocket = new DatagramSocket(1111);
//准备数据
//这是一个固定写法
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
String msg = reader.readLine();
byte[] bytes = msg.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress("localhost",2222));
datagramSocket.send(datagramPacket);
if (msg.equals("bye")){
break;
}
}
datagramSocket.close();
}
}
服务端:
public class UdpReceiveDemo01 {
public static void main(String[] args) throws Exception{
DatagramSocket datagramSocket = new DatagramSocket(2222);
while (true){
//准备接收包裹
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
//阻塞接收包裹
datagramSocket.receive(datagramPacket);
//断开连接,实现聊天关键字,例如发送端发bye就断开
byte[] data = datagramPacket.getData();
String recevieData = new String(data,0,data.length);
System.out.println(recevieData);
if (recevieData.equals("bye")){
break;
}
}
datagramSocket.close();
}
}
Udp多线程在线咨询
理解使用多线程实现聊天的工作流程
发送端:
//原有基础上添加线程
public class TalkSend implements Runnable{
//提高DatagramSocket、BufferedReader的作用域
DatagramSocket datagramSocket = null;
BufferedReader bufferedReader = null;
//发送端需要端口,地址,对方端口
private int fromport;
private String IP;
private int toPort;
public TalkSend(int fromport, String IP, int toPort) {
this.fromport = fromport;
this.IP = IP;
this.toPort = toPort;
try {
datagramSocket = new DatagramSocket(fromport);
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
}catch (IOException e){
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true){
String msg = bufferedReader.readLine();
byte[] bytes = msg.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress(this.IP,this.toPort));
datagramSocket.send(datagramPacket);
if (msg.equals("bye")){
break;
}
}
}catch (Exception e){
e.printStackTrace();
}
datagramSocket.close();
}
}
接收端
public class TalkReceive implements Runnable{
DatagramSocket datagramSocket = null;
//接收端只需要端口、msgfrom作为备注提示是那方发送的信息
private int fromport;
private String msgfrom;
public TalkReceive(int fromport, String msgfrom) {
this.fromport = fromport;
this.msgfrom = msgfrom;
try {
datagramSocket = new DatagramSocket(fromport);
}catch (IOException e){
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true){
//准备接收包裹
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
//阻塞接收包裹
datagramSocket.receive(datagramPacket);
//断开连接,实现聊天关键字,例如发送端发bye就断开
byte[] data = datagramPacket.getData();
String recevieData = new String(data,0,data.length);
System.out.println(msgfrom+":"+recevieData);
if (recevieData.equals("bye")){
break;
}
}
}catch (IOException e){
e.printStackTrace();
}
datagramSocket.close();
}
}
老师
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend(3333,"localhost",4444)).start();
new Thread(new TalkReceive(2222,"学生")).start();
}
}
学生
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(1111,"localhost",2222)).start();
new Thread(new TalkReceive(4444,"老师")).start();
}
}
URL下载网络资源
理解如果通过url下载网络上的资源
Url例如:https://www.baidu.com/
全程:统一资源定位符,定位互联网的某一个资源
DNS域名解析:www.baidu.com本质上还是解析为 xxx.xxx.x.x,域名只是为了方便记忆
协议:ip地址:端口/项目名/资源
public class UrlDown {
public static void main(String[] args) throws Exception{
//1、下载地址
URL url = new URL("https://p1.music.126.net/ukMMQAeIixCM22VfN6IF_w==/109951166427062169.jpg");
//2、连接到这个Ip
// 此处的urlConnection对象实际上是根据URL的 请求协议(此处是http)生成的URLConnection类
// 的子类HttpURLConnection,故此处最好将其转化为HttpURLConnection类型的对象,以便用到
// HttpURLConnection更多的API.如下:
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("SY.jpg");
byte[] bytes = new byte[999999999];
int len;
if ((len=inputStream.read(bytes))!=-1){
fos.write(bytes,0,bytes.length);
}
inputStream.close();
fos.close();
urlConnection.disconnect();
}
}
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("https://www.baidu.com/");
//协议
System.out.println(url.getProtocol());
//主机IP
System.out.println(url.getHost());
//端口
System.out.println(url.getPort());
//文件
System.out.println(url.getPath());
//全路径
System.out.println(url.getFile());
//参数
System.out.println(url.getQuery());
}
}

浙公网安备 33010602011771号