网络编程
网络通信概述
什么是网络
- 计算机网络是指两台或更多的计算机组成的网络,在同一个网络中,任意两台计算机都可以直接通 信,因为所有计算机都需要遵循同一种网络协议。
协议
计算机网络中为了进行数据交换而建立的规则,标准或约定集合。
- 对某个特定的计算机网络来说,它可能使用网络协议ABC,而另一个计算机网络可能使用网络协议 XYZ。如果计算机网络各自的通讯协议不统一,就没法把不同的网络连接起来形成互联网。因此,为了 把计算机网络接入互联网,就必须使用TCP/IP协议。
- TCP/IP协议泛指互联网协议,其中最重要的两个协议是TCP协议和IP协议。只有使用TCP/IP协议的计 算机才能够联入互联网,使用其他网络协议(例如NetBIOS、AppleTalk协议等)是无法联入互联网的。
OSI/RM模型
- 国际标准化组织(nternational Organization for Standardization, ISO)制定一套标准,我们就全部采用那套标准。这一提议得到了计算机企业的广泛认可。于是ISO就制定了开放系统互连(OSI)模型,并由全世界的计算机企业以此为标准开发和建立计算机网络。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-plmwVo8U-1668596349284)(C:\Users\MX\AppData\Roaming\Typora\typora-user-images\image-20221115155629944.png)]
端口
- 动态端口是从1024~65535 , 动态是指不固定的端口分配
- 我们可以通过 netstat命令来查看已经分配的端口
IP地址
什么是IP地址
- IP地址是指互联网协议地址,是IP协议提供的一种统一的地址格式,他为互联网上的每一个网络和每一个主机分配一个逻辑地址,依次来屏蔽物理地址的差异
IP地址的作用
- 在互联网中,一个IP地址用于唯一标识一个网络接口(Network Interface)。一台联入互联网的计 算机肯定有一个IP地址,但也可能有多个IP地址。
IP地址的分类
- IPv4
IPv4采用32位地址,类似 101.202.99.12
IPv4地址总共有232个(大约42亿)
IPv4的地址目前已耗尽
- IPv6
IPv6采用128位地址, 类似 2001:0DA8:100A:0000:0000:1020:F2F3:1428
IPv6 地址则总共有2128个(大约340万亿亿亿亿)
IPv6的地址是根本用不完的
- A类:1.0.0.1 ~ 127.255.255.254 1个网络号段 + 3个主机号段
- B类:128.0.0.1 ~ 191.255.255.254 2个网络号段 + 2个主机号段
- C类:192.0.0.1 ~ 223.255.255.254 3个网络号段 + 1个主机号段
- D类:224.0.0.1 ~ 239.255.255.254
- E类:240.0.0.1 ~ 247.255.255.254
x.x.x.255为广播地址;x.x.x.0为网络地址
UDP编程 (追求速度的网络协议)用户数据报协议
- 无连接
- 不可靠
- 不安全
- 速度快
发送数据
简单的UDP编程,实现从本机端口8080 向 本机8880端口发送一个信息
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
/**
* @author : YWJ
* @date : 2022/11/15 : 17:46
*/
public class Demo {
public static void main(String[] args) {
DatagramSocket datagramSocket = null ;
Scanner sc = new Scanner(System.in);
try{
datagramSocket = new DatagramSocket(9999);
while (true) {
System.out.print("你要发送:");
String msg = sc.nextLine();
byte[] bytes = msg.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress("127.0.0.1", 8888));
datagramSocket.send(datagramPacket);
System.out.println("数据发送成功");
}
} catch (IOException e) {
e.printStackTrace();
}finally {
assert datagramSocket != null;
datagramSocket.close();
}
}
}
- DatagramSocket 对象,是java基于UDP网络协议封装的Socket(套接字)
- DatagramPacket 对象 , 进行数据的封装和解封装
接受数据
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* @author : YWJ
* @date : 2022/11/15 : 19:11
*/
public class Demo02 {
public static void main(String[] args) {
DatagramSocket datagramSocket = null ;
try{
datagramSocket = new DatagramSocket(8888);
while(true){
byte[] bytes = new byte[10];
DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
System.out.println("正在等待客户端发送数据------");
//等待接收数据
datagramSocket.receive(datagramPacket);
System.out.println("接收到数据------");
//将数据转换出来
byte[] msg = datagramPacket.getData();
String sendIP = datagramPacket.getAddress().getHostAddress();
int sendPort = datagramPacket.getPort();
System.out.println("接收到来自 "+ sendIP+":"+sendPort+" 的信息:"+new String(msg,0,datagramPacket.getLength()));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(datagramSocket!=null){
datagramSocket.close();
}
}
}
}
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tcFMGEO6-1668596349286)(C:\Users\MX\AppData\Roaming\Typora\typora-user-images\image-20221115201106628.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a358zH1u-1668596349287)(C:\Users\MX\AppData\Roaming\Typora\typora-user-images\image-20221115201042468.png)]
使用多线程实现收发一体的UDP
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
/**
* @author : YWJ
* @date : 2022/11/15 : 20:12
*/
public class Demo03 {
public static final String DES_IP = "127.0.0.1";
public static final int DEC_PORT = 8888;
public static void main(String[] args) {
DatagramSocket datagramSocket = null ;
Scanner sc = new Scanner(System.in);
try{
datagramSocket = new DatagramSocket(9999);
UDPReceiveMsg udpReceiveMsg = new UDPReceiveMsg(datagramSocket);
udpReceiveMsg.start();
while (true) {
String msg = sc.nextLine();
byte[] bytes = msg.getBytes(StandardCharsets.UTF_8);
InetSocketAddress inetSocketAddress = new InetSocketAddress(DES_IP,DEC_PORT);
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length,inetSocketAddress);
datagramSocket.send(datagramPacket);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
assert datagramSocket != null;
datagramSocket.close();
}
}
}
class UDPReceiveMsg extends Thread{
private DatagramSocket datagramSocket;
public UDPReceiveMsg(DatagramSocket socket){
this.datagramSocket = socket ;
}
@Override
public void run() {
try {
receiveMsg();
} catch (IOException e) {
e.printStackTrace();
}
}
private void receiveMsg() throws IOException {
while(true) {
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
//等待接收数据
datagramSocket.receive(datagramPacket);
//将数据转换出来
byte[] msg = datagramPacket.getData();
System.out.println(">>" + new String(msg, 0, datagramPacket.getLength(), StandardCharsets.UTF_8));
}
}
}
TCP编程(传输控制协议)
- 安全 , 可靠 , 有连接 , 点对点的,长链接
两台客户端的交互,由服务端作为中间的传递者
在与服务端数据传输的过程中,
有TCP三步握手工作
- 简单实现一个服务器,和客户端
//服务器
package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author : YWJ
* @date : 2022/11/16 : 12:01
*/
public class TCPDemo01 {
//服务器
public static void main(String[] args){
ServerSocket serverSocket = null ;
try{
serverSocket = new ServerSocket(8080);
while(true){
System.out.println("服务器开始运行,等待客户端中------");
Socket accept = serverSocket.accept();
System.out.println(accept.getInetAddress().getHostName());
//推送一条消息
String msg = "欢迎你访问qq";
OutputStream outputStream = accept.getOutputStream();
PrintWriter out = new PrintWriter(outputStream,true);
out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(serverSocket!= null){
try{
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
//客户端
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
/**
* @author : YWJ
* @date : 2022/11/16 : 12:44
*/
public class TCPDemo02 {
public static final String DES_IP = "127.0.0.1";
public static final int DEC_PORT = 8080;
public static void main(String[] args) {
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress(DES_IP,DEC_PORT));
System.out.println("成功连接到服务器");
InputStream inputStream = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr);
String line = null ;
while((line = br.readLine())!= null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 实现收发共存的客户端
package TCP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Scanner;
/**
* @author : YWJ
* @date : 2022/11/16 : 16:55
*/
public class TCPClient extends Thread{
public static final String DES_IP = "127.0.0.1";
public static final int DEC_PORT = 8080;
Socket socket = null ;
public TCPClient(Socket socket){
this.socket = socket;
}
public static void main(String[] args) {
Socket socket = null ;
PrintWriter out = null ;
Scanner sc = null ;
try {
socket = new Socket();
sc = new Scanner(System.in);
socket.connect(new InetSocketAddress(DES_IP,DEC_PORT));
//启动线程
new TCPClient(socket).start();
//数据接受
try{
while(true){
String msg = sc.nextLine();
out = new PrintWriter(socket.getOutputStream(),true);
out.println(msg);
}
}catch (Exception e){
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
receiveMsg();
}
private void receiveMsg() {
BufferedReader br = null ;
try {
while (true) {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg = null;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
}
}
}catch (IOException e){
e.printStackTrace();
}
}
}
- 实现收发一体的服务端
package TCP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* @author : YWJ
* @date : 2022/11/16 : 17:53
*/
public class TCPSever {
public static void main(String[] args) {
ServerSocket serverSocket = null ;
try{
serverSocket = new ServerSocket(8080);
System.out.println("服务器等待客户端连接中------");
while(true){
Socket socket = serverSocket.accept();
//接受数据
new SocketClient(socket).start();
//发送数据
new SocketPast(socket).start();
}
}catch (IOException e){
e.printStackTrace();
}finally{
}
}
}
class SocketClient extends Thread{
private Socket socket;
public SocketClient(Socket socket){
this.socket = socket ;
}
@Override
public void run() {
System.out.println("客户端"+socket.getInetAddress().getHostName()+"上线了");
BufferedReader br = null ;
try{
while(true){
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg = null ;
while((msg = br.readLine())!=null){
System.out.println(msg);
}
}
}catch (IOException e){
e.fillInStackTrace();
}
}
}
class SocketPast extends Thread{
Socket socket;
public SocketPast(Socket socket){
this.socket = socket;
}
@Override
public void run() {
PrintWriter out = null ;
Scanner sc = null ;
try{
out = new PrintWriter(socket.getOutputStream(),true);
sc = new Scanner(System.in);
while(true){
String msg = sc.nextLine();
out.println(msg);
}
}catch (IOException e){
e.printStackTrace();
}
}
}
- 在客户端关闭连接 的时候,和服务器有四次数据交互,也就是TCP四次挥手