1.网络
1.1网络概述
计算机网络:把分布在不同地域的计算机与专门的外部设备用通信线路互联成一个规模大功能强的网络系统。
网络编程的目的:直接或间接的通过网络协议与其他计算机实现数据交换,进行通讯。
网络编程中有两个主要问题:
- 如何准确地定位网络上一台或多台主机:定位主机上的特定的应用。
- 找到主机琥如何可靠高效地进行数据传输
1.2如何实现网络中的主机通信
通信双方的地址:IP、端口号
一定的规则(网络通信协议):OSI参考模型,TCP/IP协议。
1.3 IP和端口号
1.3.1 IP
IP地址:InetAddress
唯一的标识Internet上的计算机(通信实体)。本地地址(127.0.0.1) 主机名(localhost)
IP地址分为IPV4和IPV6
特点都是不容易记忆
IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节)。IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。例:点分十进IP地址(100.4.5.6),实际上是32位二进制数(01100100.00000100.00000101.00000110)。
1.3.2端口号
所谓的端口,就好像是门牌号一样,客户端可以通过ip地址找到对应的服务器端,但是服务器端是有很多端口的,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到该服务器。为了对端口进行区分,将每个端口进行了编号,这就是端口号 。
1.4 网络协议
1.4.1网络通信协议
计算机网络中实现通信必须有一些规定。对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。
1.4.2问题:网络协议太复杂
计算机网络通信涉及大量内容。比如指定原地址和目标地址。加密解密,压缩解压缩等。如何实现如此复杂的网络协议?
1.4.3 通信协议的分层思想
1.4.4 TCP/IP协议蔟
TCP/IP协议簇是Internet的基础,也是当今最流行的组网形式。TCP/IP是一组协议的代名词,包括许多别的协议,组成了TCP/IP协议簇。其中比较重要的有SLIP协议、PPP协议、IP协议、ICMP协议、ARP协议、TCP协议、UDP协议、FTP协议、DNS协议、SMTP协议等。TCP/IP协议并不完全符合OSI的七层参考模型。传统的开放式系统互连参考模型,是一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信。而TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求
TCP的优点: 可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
TCP的缺点: 慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。
UDP的优点: 快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击…… UDP的缺点: 不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。 基于上面的优缺点,那么: 什么时候应该使用TCP: 当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输 ………… 什么时候应该使用UDP: 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 TFTP ……
有些应用场景对可靠性要求不高会用到UPD,比如长视频,要求速率
小结TCP与UDP的区别:
1.基于连接与无连接;
2.对系统资源的要求(TCP较多,UDP少);
3.UDP程序结构较简单;
4.流模式与数据报模式 ;
5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。
1.4.5 TCP网络编程实例
package 网络编程基础;
import Socket入门.Server;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpTest1 {
public void client() throws IOException {
System.out.println("============正在连接==========");
InetAddress localhost = null;
Socket socket = null;
OutputStream os = null;
try {
//指定一个IP
localhost = InetAddress.getByName("localhost");
//建立一个连接,指定连接到localhost下的10000号端口
socket = new Socket(localhost, 10000);
//获取socket输出流
os = socket.getOutputStream();
//发送数据
os.write("你好服务端!".getBytes());
System.out.println("============成功发送消息!==========");
} catch (IOException e) {
e.printStackTrace();
} finally {
assert os != null;
os.close();
socket.close();
}
}
public void server() throws IOException {
System.out.println("============等待连接==========");
//创建一个服务端Socket
ServerSocket serverSocket = new ServerSocket(10000);
//调用Accept方法,接收来自于客户端的Socket
Socket socket = serverSocket.accept();
System.out.println("============收到连接=========="+socket.toString());
//获取客户端的输入流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取输入流的数据
String line = bufferedReader.readLine();
System.out.println("收到来自"+socket.getInetAddress()+"的消息:"+line);
bufferedReader.close();
socket.close();
serverSocket.close();
}
public static void main(String[] args) throws IOException, InterruptedException {
TcpTest1 tcpTest1 = new TcpTest1();
new Thread(()->{
try {
Thread.sleep(2000);
tcpTest1.client();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}).start();
tcpTest1.server();
}
}
客户端发送文件到服务端:
package 网络编程基础;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpTest3 {
public void client() throws IOException {
System.out.println("============正在连接==========");
InetAddress localhost = null;
Socket socket = null;
OutputStream os = null;
try {
//指定一个IP
localhost = InetAddress.getByName("localhost");
//建立一个连接,指定连接到localhost下的10000号端口
socket = new Socket(localhost, 9090);
//获取socket输出流
os = socket.getOutputStream();
//将文件读取到os中
FileInputStream fileInputStream = new FileInputStream(new File("2021JavaEE学习路线图.jpg"));
//创建缓冲区
byte[] bytes = new byte[1024];
int read;
while ((read = fileInputStream.read(bytes)) != -1){
//发送数据
os.write(bytes,0,read);
}
//表示图片已经传完,结束阻塞
socket.shutdownOutput();
System.out.println("============成功发送文件!==========");
//获取客户端的输入流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取输入流的数据
String line = bufferedReader.readLine();
System.out.println("客户端随后收到来自"+socket.getInetAddress()+"的消息:"+line);
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
assert os != null;
os.close();
socket.close();
}
}
public void server() throws IOException {
System.out.println("============等待客户端连接==========");
//创建一个服务端Socket
ServerSocket serverSocket = new ServerSocket(9090);
//调用Accept方法,接收来自于客户端的Socket
Socket socket = serverSocket.accept();
System.out.println("============收到连接=========="+socket);
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(new File("2021JavaEE学习路线图222.jpg"));
//创建缓冲区
byte[] bytes = new byte[1024];
int read;
while ((read = inputStream.read(bytes)) != -1){
//发送数据
fileOutputStream.write(bytes,0,read);
}
//反馈一下
OutputStream outputStream = socket.getOutputStream();
outputStream.write("已经收到文件!".getBytes());
outputStream.close();
fileOutputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
}
public static void main(String[] args) throws IOException {
TcpTest3 tcpTest1 = new TcpTest3();
new Thread(()->{
try {
Thread.sleep(2000);
tcpTest1.client();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}).start();
tcpTest1.server();
}
}
练习:
package 网络编程基础;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpTest4 {
/**
* 客户端发送文本,服务端转大写再返回给客户端
*/
public void client() throws IOException {
Socket socket;
OutputStream os = null;
BufferedReader bufferedReader = null;
try {
socket = new Socket(InetAddress.getByName("localhost"), 9090);
os = socket.getOutputStream();
//发送数据
os.write("abcdefg".getBytes());
socket.shutdownOutput();
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("客户端接收到服务器返回的消息" + bufferedReader.readLine());
} catch (IOException e) {
} finally {
os.close();
bufferedReader.close();
}
}
public void server() throws IOException {
ServerSocket serverSocket = new ServerSocket(9090);
Socket socket = serverSocket.accept();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = bufferedReader.readLine();
System.out.println("服务器接收到信息:" + str);
OutputStream outputStream = socket.getOutputStream();
outputStream.write(str.toUpperCase().getBytes());
System.out.println("服务器转大写后发送信息");
serverSocket.close();
socket.close();
outputStream.close();
bufferedReader.close();
}
public static void main(String[] args) throws IOException, InterruptedException {
TcpTest4 tcpTest1 = new TcpTest4();
new Thread(()->{
try {
Thread.sleep(2000);
tcpTest1.client();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}).start();
tcpTest1.server();
}
}