Java基础----网络编程基础 笔记

1、网络基础

  1. 网络通讯

    1. 概念:两台设备之间通过网络实现数据传输
    2. 网络通信:将数据通过网络从一台设备传输到另一台设备
    3. java.nat包下提供了一系列的类或接口,供程序员使用,完成网络通信在这里插入图片描述
  2. 网络

    1. 概念:两台或多台设备通过一定物理设备连接起来构成了网络
    2. 根据网络的覆盖范围不同,对网络进行分类:
      局域网:覆盖范围最小,仅仅覆盖一个教室或者一个机房
      城域网:覆盖范围较大,可以覆盖一个城市
      广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网时广域网的代表
  3. ip地址

    1. 概念:用于唯一事变网络中的每一台计算机
    2. 查看ip地址的表示形式:点分十进制:xx.xx.xx.xx
    3. 每一个十进制数的范围0~255
    4. 查看IP地址:ipconfig
    5. IP地址的组成=网络地址+主机地址
    6. ipv6是互联网工程任务组设计的用于替代iPv4的下一代ip协议,其地址数量号称可以为全世界的每一粒沙子编上一个地址
    7. 由于ipv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。Ipv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
    8. ipv4地址的分类
      在这里插入图片描述
  4. 域名

    1. 概念:将ip地址映射成域名,例如www.baidu.com
    2. 好处:方便记忆
  5. 端口号

    1. 概念:用于表示计算机上某一个特定的网络程序
    2. 表示形式:以整数形式,范围:0~65535
    3. 0~1024已经被占用:比如ssh是22,ftp是21,smtp是25,http是80
    4. 常见的网络程序端口号:
      1. tomcat:8080
      2. mysql:3306
      3. oracle:1521
      4. sqlserver:1433
  6. 网络通信协议
    数据的组织形式,例如tcp/ip协议
    在这里插入图片描述

  7. 传输层的TCP和UDP协议

    1. TCP协议:传输控制协议
      1. 使用TCP协议前,须先建立TCP连接,形成传输数据通道
      2. 传输前采用”三次握手“方式,是可靠的
      3. TCP协议进行通信的两个应用程序:客户端、服务端
      4. 在连接中可进行大数据量的传输
      5. 传输完毕,需释放已建立的连接,效率低

    2.UDP协议
    1. 将数据、源、目的封装成数据包,不需要建立连接
    2. 每个数据报的大小限制在64k内
    3. 因无需连接,故是不可靠的
    4. 发送数据结束时无需释放资源(因为不是面向连接的),速度快

2、InetAddress

  1. 相关方法
    1. getLocalHost:获取本机InetAddress对象
    2. getByName:根据指定主机名/域名获取ip地址对象
    3. getHostName:获取InetAddress对象的主机名
    4. getHostAddress:获取InetAddress对象的地址
import java.net.InetAddress;
import java.net.UnknownHostException;

//演示InetAddress类的使用
public class API_ {
    
    
    public static void main(String[] args) throws UnknownHostException {
    
    
        //1.获取本机的InetAddress对象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);
        //2.根据指定主机名/域名获取ip地址对象
        InetAddress byName = InetAddress.getByName("LAPTOP-7KBLS3C4");
        System.out.println(byName);
        InetAddress byName1 = InetAddress.getByName("www.baidu.com");
        System.out.println(byName1);
        //3.通过InetAddress对象获取对应的地址
        System.out.println(byName1.getHostAddress());
        //4.通过InetAddress对象,获取对应的主机名域名
        System.out.println(byName1.getHostName());
    }
}

在这里插入图片描述

3、Socket

  1. 基本介绍:
    1. 套接字(Socket)开发网络应用程序被广泛采用,以至于称为事实上的标准
    2. 通信的两端都要有套接字,是两台机器间通信的端点
    3. 网络通信其实就是套接字(Socket)间通信
    4. Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
    5. 一般主动发起通信的应用程序属于客户端,等待通信请求的为服务端
    6. 基于客户端-服务器端的网络通信
    7. 底层使用的是TCP/IP协议
    8. 基于socket的TCP编程和UDP编程
  2. 当我们需要通信时(读写数据):
    1. socket.getOutputStream()
    2. socket.getInputStream()

4、TCP编程

  1. 基本步骤:
    服务器端:
    (1)监听端口ServerSocket serverSocket = new ServerSocket(9999);
    (2)创建套接字对象Socket accept = serverSocket.accept();
    在这里插入图片描述
    (3)生成输入字节流 InputStream inputStream = socket.getInputStream()
    (4)IO读取
    (5)关闭流对象和套接字对象

    客户端:
    (1)连接服务器端(ip,端口)Socket socket = new Socket("127.0.0.1", 9999);
    (2)生成输出字节流OutputStream outputStream = socket.getOutputStream();
    (3)写入outputStream.write("hello server".getBytes());
    (4)设置一个结束标记socket.shutdownOutput();
    (5)关闭流对象和套接字对象

  2. 基于socket的TCP编程示例(字节流):
    服务器端:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketTCP01Server {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //当没有客户端连接9999端口时,程序会阻塞,等待连接
        //如果客户端连接,则会返回Socket对象,程序继续
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端在9999端口监听,等待连接。。。");

        Socket accept = serverSocket.accept();
        System.out.println("服务端socket="+accept.getClass());
        //通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
        InputStream inputStream = accept.getInputStream();
        //IO读取
        byte[] buf = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(buf))!=-1){
    
    
            System.out.println(new String(buf,0,readLen));
        }

        OutputStream outputStream = accept.getOutputStream();
        //通过输出流,写入数据到数据通道
        outputStream.write("hello client".getBytes());
        accept.shutdownOutput();
        //关闭输入流和Socket
        inputStream.close();
        outputStream.close();
        accept.close();
        serverSocket.close();
    }
}

客户端:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class SocketTCP01Client {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //连接服务器端(ip,端口)
        Socket socket = new Socket("127.0.0.1", 9999);
        System.out.println("客户端socket返回="+socket.getClass());
        //连接上后,生成socket,通过socket.getOutputStream()得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //通过输出流,写入数据到数据通道
        outputStream.write("hello server".getBytes());
        //设置一个结束标记
        socket.shutdownOutput();

        InputStream inputStream = socket.getInputStream();
        //IO读取
        byte[] buf = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(buf))!=-1){
    
    
            System.out.println(new String(buf,0,readLen));
        }
        //关闭流对象和socket,必须关闭
        outputStream.close();
        inputStream.close();
        socket.close();
    }
}
  1. 基于socket的TCP编程示例(字符流):
    StreamUtils类:
import java.io.*;

public class StreamUtils {
    
    
    //将输入流转换成byte[],即可以把文件的内容读入到byte[]
    public static byte[] streamToByteArray(InputStream is) throws IOException {
    
    
        ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
        byte[] b = new byte[1024];//字节数组
        int len;
        while ((len=is.read(b))!=-1){
    
    
            bos.write(b,0,len);//把读取的数据写入到bos
        }
        byte[] array = bos.toByteArray();
        bos.close();
        return array;
    }
    public static String streamToString(InputStream is) throws IOException {
    
    
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
        StringBuffer stringBuffer = new StringBuffer();
        String line;
        while ((line=bufferedReader.readLine())!=null){
    
    //当读到null就结束了
            stringBuffer.append((line+"\r\n"));
        }
        return bufferedReader.toString();
    }
}

服务器端:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketTCP01Server {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //当没有客户端连接9999端口时,程序会阻塞,等待连接
        //如果客户端连接,则会返回Socket对象,程序继续
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端在9999端口监听,等待连接。。。");

        Socket accept = serverSocket.accept();
        System.out.println("服务端socket="+accept.getClass());
        //通过socket.getInputStream()读取客户端写入到数据通道的数据,显示
        InputStream inputStream = accept.getInputStream();
        //IO读取
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);

        OutputStream outputStream = accept.getOutputStream();
        //通过输出流,写入数据到数据通道
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello client字符流");
        bufferedWriter.newLine();
        bufferedWriter.flush();
        //关闭输入流和Socket
        bufferedReader.close();
        bufferedWriter.close();
        accept.close();
        serverSocket.close();

    }
}

客户端:

import java.io.*;
import java.net.Socket;

public class SocketTCP01Client {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //连接服务器端(ip,端口)
        Socket socket = new Socket("127.0.0.1", 9999);
        System.out.println("客户端socket返回="+socket.getClass());
        //连接上后,生成socket,通过socket.getOutputStream()得到和socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        //通过输出流,写入数据到数据通道
        bufferedWriter.write("hello server字符流");
        //设置一个结束标记
        bufferedWriter.newLine();
        bufferedWriter.flush();

        InputStream inputStream = socket.getInputStream();
        //IO读取
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);
        //关闭流对象和socket,必须关闭
        bufferedReader.close();
        bufferedWriter.close();
        socket.close();
    }
}
  1. 示例3
    在这里插入图片描述
    服务器端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

//服务器端
public class TCPFileUploadServer {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //1.服务端在本机监听8888
        ServerSocket serverSocket = new ServerSocket(8888);
        //2.等待连接
        System.out.println("服务器在8888端口监听。。。");
        Socket accept = serverSocket.accept();

        //3.读取客户端发送的数据
        //通过Socket得到输入流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(accept.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
        //4.将得到bytes数组写入到指定的路径
        String destFilePath = "D:\\qieeeee.jpg";
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));
        bufferedOutputStream.write(bytes);
        bufferedOutputStream.close();

        //向客户端回复“收到图片”
        BufferedWriter bufferedWriter  = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bufferedWriter.write("收到图片");
        bufferedWriter.flush();//把内容刷新到数据通道
        //设置一个结束标记
        accept.shutdownOutput();
        bufferedWriter.close();

        bufferedInputStream.close();
        accept.close();
        serverSocket.close();
    }
}

客户端:

import java.io.*;
import java.net.Socket;

//客户端
public class TCPFileUploadClient {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //客户端连接服务器,得到Socket对象
        Socket socket = new Socket("127.0.0.1", 8888);
        System.out.println("连接服务器成功。。。。。");
        //创建读取磁盘文件的输入流(输入图片数据到程序)
        String filePath = "D:\\壁纸1.jpg";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
        //bytes是filePath对应的字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //通过socket获取到输出流,将bytes数据发送给服务器
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
        //将文件对应的字节数组的内容写入到数据通道
        bufferedOutputStream.write(bytes);
        bis.close();
        socket.shutdownOutput();

        //收到”收到图片“
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s=bufferedReader.readLine();
        System.out.println(s);
        bufferedReader.close();
        /*InputStream inputStream = socket.getInputStream();
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);*/

        inputStream.close();
        bufferedOutputStream.close();
        socket.close();
    }
}

5、UDP编程(了解)

  1. 基本介绍:

    1. DatagramSocketDatagramPacket实现了基于UDP协议网络程序
    2. UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达
    3. DatagramSocket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
    4. UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接
    5. 没有明确的服务端和客户端,演变为数据的发送端和接收端
    6. 接收数据和发送数据是通过DatagramSocket对象来完成
    7. 将数据封装到DatagramPacket对象(装包)
    8. 当接收到DatagramPacket对象需要进行拆包,取出数据
    9. DatagramSocket可以指定在哪个端口接收数据
  2. 基本流程

    1. 核心的两个类/对象DatagramSocketDatagramPacket
    2. 建立发送端,接收端
    3. 建立数据
    4. 调用DatagramSocket的发送、接收方法
    5. 关闭DatagramSocket
  3. 示例:
    在这里插入图片描述
    Udp_A.java:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

//先是接收端,再是发送端
public class Udp_A {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //1.创建一个DatagramSocket对象,准备在9999接收或发送数据
        DatagramSocket datagramSocket = new DatagramSocket(9999);

        //2. 构建一个DatagramSocket对象,准备接收数据
        //在前面讲解UDP协议的时候,说过每个数据包大小在64k以内
        byte[] buf = new byte[64*1024];
        DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);

        //3. 准备 调用 接收方法(包好的数据包,需要拆包)
        //并且填充到datagramPacket
        //当有数据包发送到本机的9999端口时,就会接收到数据,没有数据包发送就会阻塞等待
        System.out.println("等待接收数据。。。。。");
        datagramSocket.receive(datagramPacket);

        //4. 可以把datagramPacket进行拆包,取出数据并且显示
        int len = datagramPacket.getLength();//实际接收的数据字节长度
        byte[] data = datagramPacket.getData();//接收的数据
        String s = new String(data,0,len);
        System.out.println(s);

//=================================回复B的,发送
        //将需要发送的数据 封装到datagramPacket对象
        data = "收到了B的发送,我(A)也要发送了".getBytes();
        //封装的datagramPacket对象,data内容字节数组、其数组长度、主机IP、端口号
        DatagramPacket datagramPacket1 =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.199.1"),9998);

        //发送
        datagramSocket.send(datagramPacket1);
//==============================================

        //5. 关闭资源
        datagramSocket.close();
    }
}

Udp_B.java:

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

//先是发送端,再是接收端
public class Udp_B {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //1.创建一个DatagramSocket对象,准备在9998发送数据
        DatagramSocket datagramSocket = new DatagramSocket(9998);

        //2. 将需要发送的数据 封装到datagramPacket对象
        byte[] data = "哈哈哈UDP,我(B)要发送了".getBytes();
        //封装的datagramPacket对象,data内容字节数组、其数组长度、主机IP、端口号
        DatagramPacket datagramPacket =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.199.1"),9999);

        //3. 发送
        datagramSocket.send(datagramPacket);

//===================接收A的数据===============================================
        //构建一个DatagramSocket对象,准备接收数据
        byte[] buf = new byte[64*1024];
        datagramPacket = new DatagramPacket(buf, buf.length);

        //准备 调用 接收方法(包好的数据包,需要拆包)
        datagramSocket.receive(datagramPacket);

        //可以把datagramPacket进行拆包,取出数据并且显示
        int len = datagramPacket.getLength();//实际接收的数据字节长度
        data = datagramPacket.getData();//接收的数据
        String s = new String(data,0,len);
        System.out.println(s);
//===================接收A的数据=================================================

        //4. 关闭资源
        datagramSocket.close();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_55935744/article/details/123671512