网络编程
1.1计算机网络
2. 网络模型
2.1 OSI参考模型
- OSI(Open System Interconnection)开放式系统互联。
这个模型把整个网络的建设分成了七层,下层为上层服务:
- 第七层:应用层负责文件访问和管理、可靠运输服务、远程操作服务。(HTTP、FTP、SMTP)
- 第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCII格式传输。
- 第五层:会话层负责使应用建立和维持会话,使通信在失效时继续恢复通信。(断点续传)
- 第四层:传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排。(TCP、UDP)
- 第三层:网络层负责定义了能够标识所有网络结点的逻辑地址。(IP地址)
- 第二层:链路层在物理层上,通过规程或者协议(差错控制)来控制传输数据的正确性。(MAC)
- 第一层:物理层为设备之间的数据通信提供信号和物理介质。(双绞线、光导纤维)
举个实际例子,假设我在QQ上给我的学妹发了条“我喜欢你”,这条信息会从应用层向下到物理层进行传递,每下一层都会包裹某种协议,最后在物理层转换为数字信号或者光信号等通过网卡或者路由器等传递到学妹端的物理层,这种信号又从物理层往上到应用层,学妹就能看见我发了条信息,学妹也能以这样的方式给我回复消息,有可能是“你是个好人”等其他信息,这是一个双向的传递。在这个过程中,涉及到各层的协议,协议实际就是约定数据传输的格式,我发送了中文,别人也一定看到的是同样的内容。
2.2 TCP/IP模型
- 一组用于实现网络互连的通信协议,将协议分为四个层次。
由于OSI参考模型采用的是七层的建设模型,比较复杂,所以在网络建设中一般采用的是TCP/IP模型。实际上TCP/IP模型的四层也对应这OSI模型的七层,它将OSI的五到七层合成了应用层,把一二层合成了网络接口层。
- 第四层:应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是HTTP、FTP等。
- 第三层:传输层负责传送文本数据,主要协议是TCP、UDP协议。
- 第二层:网络层负责分配地址和传送二进制数据,主要协议是IP协议。
- 第一层:接口层负责电路连接,是整个网络的物理基础,典型的协议包括以太网、ADSL等等。
3. 通信协议
3.1 TCP协议
- TCP协议:Transmission Control Protocol 传输控制协议
- 是一种面向连接的、可靠的、面向字节流的传输层通信协议。数据大小无限制。建立连接的过程需要三次握手,断开连接的过程需要四次挥手。
- 面向连接的意思就是两台计算机(应用程序)在通信之前,必须先建立连接。
- TCP的三次握手,或者说三报文握手,是TCP建立连接过程的机制。主动发起TCP连接的应用进程叫做客户,而被动等待连接建立的应用程序叫做服务器。客户向服务器发送请求后,服务器要确认客户的连接请求,然后客户要对服务器的确认进行确认。
- TCP的四次挥手,或者说四报文握手,是TCP释放连接过程的机制。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后就进入了半关闭状态。当另一方也没有数据再发送时,则发送连接释放通知,对方确认后就完全关闭了TCP连接。
- “面向字节流”的含义是:虽然应用程序和TCP的交互试一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。TCP并不知道所传送的字节流的含义。TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系(例如,发送方应用程序交给发送方的TCP共10个数据块,但接收方的TCP可能只用了4个数据块就把收到的字节流交付给上层的应用程序)。但接收方的应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。
3.2 UDP协议
- UDP协议:User Datagram Protocol用户数据报协议
- 是一种无连接的传输层协议,提供面向报文的简单不可靠信息传送服务,每个包的大小是64KB。
- 无连接是指UDP在传送数据之前不需要先建立连接。远地主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP却是一种最有效的工作方式。
- “面向报文”简单说就是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。也就是说,UDP一次交付一个完整的报文。
3.3 IP协议
IP协议:Internet Protocol 互联网协议/网际协议
- 负责数据从一台机器发送到另一台机器。
- 给互联网每台设备分配一个唯一标识(IP地址)。
IP地址分为两种:
-
IPV4:4字节32位整数,并分成4段8位的二进制数,每8位之间用圆点隔开,每8位整数可以转换为一个0~255的十进制整数。 格式:D.D.D.D 例如:255.255.255.255 IPV4是上个世纪70年代出现的一个版本,到现在差不多五十年,所以面临着一个资源耗尽的问题。在上个世纪90年代出现了IP的第6个版本,据说IPV6可以给地球的每一个沙子分配一个IP。 -
IPV6:16字节128位整数,并分成8段十六进制数,每16位之间用圆点隔开,每16位整数可以转换为一个0~65535的十进制数。 格式:X.X.X.X.X.X.X.X 例如:FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF 这里的4和6是IP的第4个和第6个版本,版本1~3和版本5都未曾使用过。
IPV4的应用分类:
-
A类:政府机构,1.0.0.1~126.255.255.254 -
B类:中型企业,128.0.0.1~191.255.255.254 -
C类:个人用户,192.0.0.1~223.255.255.254 -
D类:用于组播,224.0.0.1~239.255.255.254 -
E类:用于实验,240.0.0.1~255.255.255.254 -
回环地址:127.0.0.1,指本机,一般用于测试使用。 -
测试IP命令:ping D.D.D.D 比如你可以打开cmd,输入ping www.baidu.com -
查看IP命令:ipconfig -
package Demo01;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TestInetAddress {
public static void main(String[] args) {
try {
InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
System.out.println(inetAddress1);
InetAddress inetAddress3 = InetAddress.getByName("localhost");
System.out.println(inetAddress3);
InetAddress inetAddress4 = InetAddress.getLocalHost();
System.out.println(inetAddress4);
InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress2);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
3.4 Port端口
package Demo01;
import java.net.InetSocketAddress;
public class TestInetSocketAddress {
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);
System.out.println(socketAddress2);
System.out.println(socketAddress1.getAddress());
System.out.println(socketAddress1.getHostName());
System.out.println(socketAddress1.getPort());
}
}
4.TCP
4.1 服务端
public class TCPServerDemo01 {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
serverSocket = new ServerSocket(9999);
socket = serverSocket.accept();
is = socket.getInputStream();
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
baos.close();
is.close();
socket.close();
serverSocket.close();
}
}
}
4.2 客户端
- 获取服务器地址
- 创建socket连接
- 发送消息
- 关闭连接
public class TcpClientDemo01 {
public static void main(String[] args) throws IOException {
Socket socket = null;
OutputStream os = null;
try {
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int port = 9999;
socket = new Socket(serverIP,port);
os = socket.getOutputStream();
os.write("您好呀".getBytes());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
os.close();
socket.close();
}
}
}
4.3 文件上传
public class TcpServerDemo02 {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9000);
System.out.println("服务器开始启动---");
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer))!=-1){
fos.write(buffer,0,len);
}
OutputStream os = socket.getOutputStream();
os.write("我接收完毕了,你可以断开了".getBytes(StandardCharsets.UTF_8));
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
public class TcpClientDemo02 {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
OutputStream os = socket.getOutputStream();
FileInputStream fis = new FileInputStream(new File("f:\\source\\2.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer))!=-1){
os.write(buffer,0,len);
}
socket.shutdownOutput();
InputStream inputStreamReader = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[1024];
int len2;
while ((len2 = inputStreamReader.read(buffer2))!=-1){
baos.write(buffer,0,len2);
}
System.out.println(baos.toString());
baos.close();
inputStreamReader.close();
fis.close();
os.close();
socket.close();
}
}
5.初识Tomcat
服务端
- 自定义 S
- Tomcat服务器 S : JAVA后台开发
客户端
6.UDP
6.1 服务端
public class UdpServerDemo01 {
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();
}
}
6.2 客户端
public class UdpClientDemo01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket();
String msg = "hello world";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
socket.send(packet);
socket.close();
}
}
6.3 聊天案例
public class UdpReceiver {
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);
if (receiveData.equals("bye")) break;
}
socket.close();
}
}
public class UdpSender {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6666));
socket.send(packet);
if(data.equals("bye")) {
break;
}
}
socket.close();
}
}
6.4 多线程互发消息案例
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() {
try {
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(msgFrom + ":" + receiveData);
if (receiveData.equals("bye")) break;
}
} catch (IOException e) {
e.printStackTrace();
}
socket.close();
}
}
package com.company.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutionException;
public class TalkSend implements Runnable {
DatagramSocket socket = null;
BufferedReader reader = null;
private int fromPort;
private String toIP;
private int toPort;
public TalkSend(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){
String data = null;
try {
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(data.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
public class TalkTeacher {
public static void main(String[] args) {
new Thread(new TalkSend(5555, "localhost", 8888)).start();
new Thread(new TalkReceive(9999, "Stu")).start();
}
}
public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(7878, "localhost", 9999)).start();
new Thread(new TalkReceive(8888, "teac")).start(); }
}
7.URL
- 统一资源定位符:定位资源,定位互联网上的某一个资源
DNS域名解析
协议:// ip 地址:端口/ 项目名 / 资源
public class UrlDown {
public static void main(String[] args) throws Exception {
URL url = new URL("http://twblog.ga/pic/dog.jpg");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("ok.jpg");
byte[] buffer = new byte[1024];
int len;
while((len = inputStream.read(buffer)) != -1){
fos.write(buffer, 0, len);
}
fos.close();
inputStream.close();
urlConnection.disconnect();
}
}
// 1. download Address
URL url = new URL("http://twblog.ga/pic/dog.jpg"); // 网络资源地址
// 2. connect HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("ok.jpg"); // 下来的命名
byte[] buffer = new byte[1024];
int len;
while((len = inputStream.read(buffer)) != -1){
fos.write(buffer, 0, len); // 写出数据
}
fos.close();
inputStream.close();
urlConnection.disconnect(); // 断开连接
}
}
|