一、网络编程
网络编程概述
网络编程 :
在网络[通信协议]下,不同计算机上运行的程序,可以进行[数据传输]
思考:
A电脑中的QQ,发送消息给B电脑中的QQ。那么需要知道[哪些条件]才能发送?
在这个故事场景下,你要怎么样才能找到这个女孩并把钱取出来?
第一步:
你要先找到这家银行,也就是银行的地址
第二步:
找到这个女孩在几号柜台工作
第三步:
按照银行的规则,填写取款单
在这个小故事中,找到这个女孩并成功取钱的要素有哪些?
银行的地址 ---- 银行的地址
柜台号 ---- 通过柜台跟客户交流并处理业务
填写取款单的规则 ----填写取款单的规则
网咯通信的关键三要素:
IP地址:
设备在网络中的地址,是唯一的标识。
端口:
应用程序在设备中唯一的标识。
协议:
数据在[网络中传输]的规则,常见的协议有UDP协议和TCP协议。
IP
IP:全称”互联网协议地址”,也称IP地址。是分配给上网设备的数字标签。常见的IP分类为:ipv4和ipv6
IP域名:
IP地址:
IPv4:
IPv6:
由于互联网的蓬勃发展,IP地址的需求量愈来愈大,而IPv4的模式下[IP的总数]是有限的。
采用128位地址长度,分成8组。
常用命令:
ipconfig:查看本机IP地址
ping { IP地址 }:检查网络是否连通
特殊IP地址:
127.0.0.1:是回送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
总结:
1.网络通信至少需要的元素:IP、端口、协议
2.IP地址是做什么的:定位网络上的设备的,有IPv4和IPv6
3.查看本机IP地址:ipconfig 查看是否与对方互通:【ping+IP】地址;例如:192.168.10.23
加一个ipv4的分类,需要讲A-E,IP组成为:网络号 + 主机号 广域网 城域网 局域网
最大的广域网是因特网
添加组播地址,广地址
InetAddress: 代表IP地址
InetAddress 的使用:
- 为了方便我们对IP地址的获取和操作,Java提供了一个类[InetAddress] 供我们使用
- InetAddress:此类表示Internet协议(IP)地址
方法名
说明
static InetAddress getByName(String host)
确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName()
获取此IP地址的主机名
String getHostAddress()
返回文本显示中的IP地址字符串
package com.socketmodule.socketdemo1; import java.net.InetAddress; import java.net.UnknownHostException; //static InetAddress getByName(String host) // 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 //String getHostName() 获取此IP地址的主机名 //String getHostAddress() 返回文本显示中的IP地址字符串 public class InetadressDemo1 { public static void main(String[] args) throws UnknownHostException { //getByName(String host)确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 InetAddress address = InetAddress.getByName("沉迷代码"); //String getHostName() 获取此IP地址的主机名 String hostName = address.getHostName(); System.out.println("主机名为" + hostName); //String getHostAddress() 返回文本显示中的IP地址字符串 String ip = address.getHostAddress(); System.out.println("IP为" + ip); } }
端口 :应用程序在设备中唯一的标识。
- 标记正在计算机设备上运行的应用程序,被规定为一个16位的二进制,范围是0~65535。
分类:
- 周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)
- 注册端口:1024~49151,分配给用户进程或某些应用程序。
- 动态端口:49152~65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配。
端口号:用两个字节表示的整数,它的取值范围是0~65535。
- 其中0~1023之间的端口号用于一些知名的网络服务或者应用。
- 我们自己使用1024以上的端口号就可以了。
注意:一个端口号只能被一个应用程序使用。
协议: 计算机网络中,连接和通信的规则被称为网络通信协议
通信协议:
网络上通信的设备,事先规定的连接规则,以及传输数据的规则被称为 网络通信协议
协议:
开放式网络互连标准:OSI网络参考模型:
OSI网络参考模型:全球 网络互联标准
TCP/IP网络模型:事实上的国际标准
UDP协议:
- 用户数据报协议(User Datagram Protocol)
- UDP是面向无连接通信协议。(音频,视频,普通数据会使用用UDP,因为速度快,丢失一些数据没有太大的影响)
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
TCP协议 :
- 传输控制协议 (Transmission Control Protocol)
- TCP协议是面向连接的通信协议。
- 速度慢,没有大小限制,数据安全。
三次握手:目的是确认通信双方,收发消息都是正常没问题的
TCP协议:三次握手建立可靠连接
四次挥手:目的是确保双方数据的收发已经完成,没有数据丢失
TCP协议:四次握手断开连接
小结:
- 网络编程:就是可以让[两台计算机]进行[数据交互]。
网络编程三要素:
- IP:设备在网络中唯一的标识。
- 端口号:应用程序在设备中唯一的标识。
- 协议:数据在传输过程中遵守的规则。
总结:
通讯协议是:
- 计算机中,连接和通信数据的规则被称为网络通信协议。
TCP通信协议的特点:
- 它是一种面向连接的可靠的通信协议。
- 传输前:采用“三次握手”方式建立连接,点对点的通信,所以可靠。
- 在连接中课进行大数据量的传输。
- 通信效率较低
UDP协议的特点是:
- 用户数据报协议(User Datagram Protocol)
- UDP是面向无连接,不可靠传输的通信协议。
- 速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
UDP通信程序:
DatagramSocket:用于创建客户端,服务端:
DatagramPacket:创建数据包:
UDP发送数据:
发送礼物的步骤:
package com.socketmodule.socketdemo2; import java.io.IOException; import java.net.*; public class ClientDemo { public static void main(String[] args) throws IOException { //1.找码头 DatagramSocket ds = new DatagramSocket(); //2.打包礼物 //DatagramPacket(byte[] buf, int length, InetAddress address, int port) String s = "送给村长老丈人的礼物"; byte[] bytes = s.getBytes(); InetAddress address = InetAddress.getByName("127.0.0.1"); int port = 10000; DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port); //3.由码头发送包裹 ds.send(dp); //4.付钱走羊 ds.close(); } }
UDP接收数据:
package com.socketmodule.socketdemo2; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class ServerDemo { //注意点: //1.要先运行接收端,再运行发送端 //2.如果接收端再启动之后,没有接收到数据,那么会死等(阻塞). //3.在接收数据的时候,需要调用一个getLength方法,表示接收到了多少字节 public static void main(String[] args) throws IOException { //1.找码头 ---- 表示接收端从10000端口接收数据的. DatagramSocket ds = new DatagramSocket(10000); //2,创建一个新的箱子 byte [] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes,bytes.length); //3.接收礼物,把礼物放到新的箱子中 System.out.println("-----------接收前----------"); ds.receive(dp); System.out.println("------------接收后---------"); //4.从新的箱子里面获取礼物 // byte[] data = dp.getData(); int length = dp.getLength(); System.out.println(new String(bytes,0,length)); //5.拿完走羊 ds.close(); } }
总结:
接收端可以反复接收数据
步骤:
package com.socketmodule.socketdemo3;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class ClientDemo {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
DatagramSocket ds = new DatagramSocket();
while (true) {
String s = sc.nextLine();
if("886".equals(s)){
break;
}
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
ds.send(dp);
}
ds.close();
}
}
package com.socketmodule.socketdemo3;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10000);
while (true) {
byte [] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
System.out.println(new String(data,0,length));
}
// ds.close();
}
}
UDP的三种通信方式
单播
组播
广播
UDP通信组播代码实现
组播地址:224.0.0.0 ~ 239.255.255.255
其中224.0.0.0 ~ 224.0.0.255 为预留的组播地址
单播的发送端
①创建发送端的Socket对象(DatagramSocket)
广播地址:255.255.255.255
package com.socketmodule.socketdemo4;
import java.io.IOException;
import java.net.*;
public class ClinetDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
String s = "hello 组播";
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("224.0.1.0");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
ds.send(dp);
ds.close();
}
}
package com.socketmodule.socketdemo4;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
MulticastSocket ms = new MulticastSocket(10000);
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
//把当前计算机绑定一个组播地址,表示添加到这一组中.
ms.joinGroup(InetAddress.getByName("224.0.1.0"));
ms.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
System.out.println(new String(data,0,length));
ms.close();
}
}
二、TCP通信程序:
TCP通信原理
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象。
通信之前要保证连接已经建立。
通过Socket产生IO流来进行网络通信。
TCP基于IO流,与UDP不区别(不需要整包)
TCP发送数据步骤
发送数据的步骤:
①创建客户端的Socket对象(Socket)与指定服务端连接
Socket(String host, int port)
②获取输出流,写数据
OutputStream getOutputStream()
③释放资源
void close()
TCP接收数据
接收数据的步骤:
①创建服务器端的Socket对象(ServerSocket)
②获取输入流,读数据,并把数据显示在控制台
③释放资源
接收数据的步骤 :
①创建服务器端的Socket对象(ServerSocket)
ServerSocket(int port)
②监听客户端连接,返回一个Socket对象
Socket accept()
③获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream()
④释放资源
void close()
package com.socketmodule.socketdemo6;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//1,创建一个Socket对象
Socket socket = new Socket("127.0.0.1",10000);
//2.获取一个IO流开始写数据
OutputStream os = socket.getOutputStream();
os.write("hello".getBytes());
/*while(true){
}*/
//3.释放资源
os.close();
socket.close();
}
}
package com.socketmodule.socketdemo6;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//1. 创建Socket对象
ServerSocket ss = new ServerSocket(10000);
//2. 等待客户端连接
System.out.println(111);
Socket accept = ss.accept();
System.out.println(222);
//3.获得输入流对象
InputStream is = accept.getInputStream();
int b;
while((b = is.read()) != -1){
System.out.print((char) b);
}
System.out.println("看看我执行了吗?");
//4.释放资源
is.close();
ss.close();
}
}
TCP发送数据原理
发送数据的步骤:
三次握手
三次握手
四次挥手
四次挥手
TCP单发:
TCP多发:
TCP通信程序练习
客户端:发送数据,接收服务器反馈
服务器:接收数据,给出反馈
TCP通信原理
TCP通信程序练习
客户端:将本地文件上传到服务器。接收服务器的反馈。
服务器:接收客户端上传的文件,上传完毕之后给出反馈。
package com.socketmodule.socketdemo7;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",35729);
OutputStream os = socket.getOutputStream();
os.write("hello".getBytes());
// os.close();如果在这里关流,会导致整个socket都无法使用
socket.shutdownOutput();//仅仅关闭输出流.并写一个结束标记,对socket没有任何影响
/*InputStream is = socket.getInputStream();
int b;
while((b = is.read()) !=-1){
System.out.println((char) b);
}*/
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line = br.readLine())!=null){
System.out.println(line);
}
br.close();
os.close();
socket.close();
}
}
h
e
l
l
o
看看我执行了吗?
Process finished with exit code 0
------------------------------------------
package com.socketmodule.socketdemo7;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(35729);
Socket accept = ss.accept();
InputStream is = accept.getInputStream();
int b;
while((b = is.read())!=-1){
System.out.println((char) b);
}
System.out.println("看看我执行了吗?");
/* OutputStream os = accept.getOutputStream();
os.write("你谁啊?".getBytes());*/
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bw.write("你谁啊?");
bw.newLine();
bw.flush();
bw.close();
is.close();
accept.close();
ss.close();
}
}
你谁啊?
Process finished with exit code 0
可见: TCP做聊天要比UDP麻烦一些
TCP通信
package com.socketmodule.socketdemo8;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(35729);
Socket accept = ss.accept();
//网络中的流,从客户端读取数据的
BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
//本地的IO流,把数据写到本地中,实现永久化存储
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day14\\ServerDir\\copy.jpg"));
int b;
while((b = bis.read()) !=-1){
bos.write(b);
}
//将字节输入流FileInputStream 转成 字符输入流 Fliereader
//通过转换流
InputStreamReader inputStreamReader = new InputStreamReader(accept.getInputStream());
//通过缓冲输入字符流
BufferedReader br = new BufferedReader(inputStreamReader);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(accept.getOutputStream());
BufferedWriter bw = new BufferedWriter(outputStreamWriter);
bw.write("上传成功");
bw.newLine();
bw.flush();
bos.close();
accept.close();
ss.close();
}
}
--------
package com.socketmodule.socketdemo8;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",35729);
//是本地的流,用来读取本地文件的.
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day14\\ClientDir\\1.jpg"));
//写到服务器 --- 网络中的流
OutputStream os = socket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
int b;
while((b = bis.read())!=-1){
bos.write(b);//通过网络写到服务器中
}
bos.flush();
//给服务器一个结束标记,告诉服务器文件已经传输完毕
socket.shutdownOutput();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line = br.readLine()) !=null){
System.out.println(line);
}
bis.close();
socket.close();
}
}