网络编程

1、网路的相关概念

(1)网络通信
  • 概念:两台设别之间通过网络实现数据传输
  • 网络通信:将数据通过网络从一台设备传输到另外一台设备
  • java.net包中提供了一系列类或接口,供程序员使用,完成网络通信
(2)网络
  • 概念:两台或多台设备通过一定的物理设备连接起来构成了网络
  • 根据网络的覆盖范围可以分为:
    • 局域网,覆盖范围小,比如一个机房,一个学校内部的局域网
    • 城域网,覆盖范围稍微大一些,可以覆盖一个城市
    • 广域网,覆盖范围最大,可以覆盖全国,甚至全球
(3)ip地址
  • 概念:用于唯一标识网络中的每台计算机/主机
  • 查看ip地址命令:ipconfig
  • ip地址的表示形式,点分十进制,每个十进制数的范围为0~255
  • ip地址的组成为:网络地址+主机地址
  • ip地址分为IPv4和IPv6(128位,16字节),IPv4(32位,4个字节)网络地址资源有限,IPv6解决了网络地址资源数量的问题,也解决了多种接入设备连入互联网的障碍
  • ip地址分类:
    java网络编程,主要掌握TCP网络编程,UDP仅做了解-LMLPHP java网络编程,主要掌握TCP网络编程,UDP仅做了解-LMLPHP
(4)域名
  • 将ip地址根据HTTP协议映射成域名,可以解决ip地址记住比较困难的问题,比如百度的域名为www.baidu.com
  • ​ 端口号
    • 用于标识计算机上某个特定的网络程序
    • 表示形式:整数形式,端口范围0~65535[两个字节表示端口 0~2^16-1]
    • 0~1024已经被占用,比如 ssh 22, ftp 21, smtp 25, http 80
    • 常用的网络程序端口号:
      • tomcat:8080
      • mysql:3306
      • oracle:1521
      • sqlserver:1433
(5)网络通信协议
  • 协议(TCP/IP):传输控制协议/因特网互联协议,又叫网络通讯协议,是Internet最基本的协议,Internet国际互联网的基础。简单的说,就是有网络层的IP协议和传输层的TCP协议组成
  • java网络编程,主要掌握TCP网络编程,UDP仅做了解-LMLPHP
(6) TCP 和 UDP
  • TCP协议:传输控制协议

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

    • 将数据、源、目的封装成数据包,不需要建立连接

    • 每个数据报的大小限制在64K内,不适合传输大量数据

    • 因无需连接,故是不可靠的

    • 发送数据结束时无需释放资源(因为不是面向连接的),速度快

2、INETADDRESS类

(1)相关方法
  1. 获取本地InetAddress对象:getLocalHost
  2. 根据指定主机名/域名获取ip地址对象:getByName
  3. 获取InetAddress对象的主机名 getHostName
  4. 获取InetAddress对象的地址 getHostAddress
(2)示例
//获取本地InetAddress对象:getLocalHost
InetAddress locolHost = InetAddress.getLocalHost();
System.out.println(locolHost);

//根据指定主机名/域名获取ip地址对象: getByName
InetAddress host2 = InetAddress.getByName("DESKTOP-TNH49H9");
System.out.println(host2);
InetAddress host3 = InetAddress.getByName("www.baidu.com");
System.out.println(host3);

//获取InetAddress对象的主机名 getHostName
String host3AName = host3.getHostName();
System.out.println(host3AName);

//获取InetAddress对象的地址 getHostAddress
String host3Address = host3.getHostAddress();
System.out.println(host3Address);

3、SOCKET

  1. 套接字(Socket)是两台机器间通信的端点,通信的两端都要有Socket
  2. 网络通信其实就是Socket间的通信
  3. Socket允许程序把网络连接当成一个六,数据在两个Socket间通过IO传输
  4. 一般主动发起通信的应用程序属于客户端,等待通信请求的为服务端

java网络编程,主要掌握TCP网络编程,UDP仅做了解-LMLPHP

4、TCP网络通信编程

(1)基本介绍
  1. 基于客户端-服务端的网络通信
  2. 底层使用的是TCP/IP协议
  3. 基于Socket的TCP编程

java网络编程,主要掌握TCP网络编程,UDP仅做了解-LMLPHP

(2)举例

图片服务端和客户端之间的交互,三个文件,一个StreamUtils类,工具类,一个服务端,一个客户端。

服务端负责接收图片并写入图片,从socket中传消息给客户端。

客户端负责读取图片并传送图片,最后从socket接收从服务端传过来的消息。

StreamUtils类:

package JavaEE.chatper16.upload;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @version 1.0
 * @auther wangweicheng
 * 流的工具包,
 */
public class StreamUtils {
    //将输入流转换为bytes
    public static byte[] streamToByteArray(InputStream is) throws Exception{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
        byte[] b = new byte[1024];
        int len;
        while((len=is.read(b))!=-1){
            bos.write(b, 0, len);
        }
        byte[] array = bos.toByteArray();
        bos.close();
        return array;
    }
    //将输入流转换为String
    public static String streamToString(InputStream is) throws Exception{
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder builder= new StringBuilder();
        String line;
        while((line=reader.readLine())!=null){ //当读取到 null 时,就表示结束
            builder.append(line+"\r\n");
        }
        return builder.toString();
    }
}

服务端TCPUploadFileServer:

package JavaEE.chatper16.upload;

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

/**
 * @version 1.0
 * @auther wangweicheng
 */
public class TCPUploadFileServer {
    public static void main(String[] args) throws Exception {
        //三个过程
        //1、从socket中读取字符文件
        //1.1 监听端口,等待连接
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务端等待连接。。。");
        Socket socket = serverSocket.accept();
        //1.2读取文件
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        //2、将字符文件转换为字节流写入到文件当中,转变为图片
        byte bytes[] = StreamUtils.streamToByteArray(bis);
        String destFilePath = "D:\\成绩单不带说明1.jpg";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
        bos.write(bytes);
        bos.close();
        //3、发消息到客户端图片完成传输,结束
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bufferedWriter.write("收到图片了");
        bufferedWriter.flush();     //刷新到socket当中
        socket.shutdownOutput();        //设置结束标记

        //关闭资源
        bufferedWriter.close();
        bos.close();
        socket.close();
        serverSocket.close();
    }
}

客户端TCPUploadFileCilent:

package JavaEE.chatper16.upload;

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

/**
 * @version 1.0
 * @auther wangweicheng
 */
public class TCPUploadFileCilent {
    public static void main(String[] args) throws Exception {
        //三个过程
        //1、从文件中读取图片转换为字节流
        //1.1建立与服务端的连接
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
        System.out.println("socket:"+socket.getClass());
        //1.2从磁盘中读取对应文件,并转换为字节流
        String filePath = "D:\\1.jpg";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
        byte bytes[] = StreamUtils.streamToByteArray(bis);
        //2、将字节流写入socket当中
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(bytes);       //写入数据通道
        bis.close();
        socket.shutdownOutput();        //设置结束标记

        //3、获取服务端传过来的消息,结束
        InputStream inputStream = socket.getInputStream();
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);

        //关闭资源
        bos.close();
        inputStream.close();
        socket.close();

    }
}
(3)netstat指令
  1. netstat -an可以查看当前主机网络情况,包括端口监听情况和网络连接情况
  2. netstat -an | more 可以分页显示
  3. 要求在dos控制台下执行win+r

5、UDP网络编程(了解)

(1)基本介绍
  • 类DatagramSocket和DatagramPacket【数据包/数据报]实现了基于UDP协议网络程序
  • UDP数据报通过套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送达目的地,也不能确定什么时候抵达
  • DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号和接收端的IP地址和端口号
  • UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方与接收方的连接
(2)基本流程
  1. 核心的两个类/对象 DatagramSocket和DatagramPacket
  2. 建立发送端、接收端(没有服务端和客户端的概念)
  3. 调用DatagramSocket的发送、接收方法
  4. 关闭DatagramSocket
(3)举例

总共分为两个文件,一个接收端UDPReceiveB,一个发送端UDPSenderA

接收端UDPReceiveB:

package JavaEE.chatper16.UDP_;

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

/**
 * @version 1.0
 * @auther wangweicheng
 */
public class UDPReceiveA {
    public static void main(String[] args) throws IOException {
        //1、创建DatagramSocket对象,准备在9999端口接收数据
        DatagramSocket socket = new DatagramSocket(9999);
        //2、接收接收端发回来的信息
        byte[]  buf = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
        //有数据就会接收数据,没有数据就会等待
        System.out.println("接收端A等待接受B端数据");
        socket.receive(datagramPacket);
        System.out.println("接收端A接受到了B端数据的数据");
        //进行拆包
        int lenth = datagramPacket.getLength();
        byte[] data = datagramPacket.getData();        //获取到数据
        System.out.println(datagramPacket);
        System.out.println(new String(data, 0, lenth));
        //3、将需要发送的数据,封装到DatagramPacket对象当中
        data = "好的,明天见".getBytes();
        //说明参数:需要封装的对象,对象的长度,主机IP,端口号
        datagramPacket = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),9998);
        socket.send(datagramPacket);

        //关闭资源
        socket.close();
        System.out.println("A端退出");

    }
}

发送端UDPSenderA

package JavaEE.chatper16.UDP_;

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

/**
 * @version 1.0
 * @auther wangweicheng
 */
public class UDPSenderB {
    public static void main(String[] args) throws IOException {
        //1、创建DatagramSocket对象,准备在9998端口发送数据
        DatagramSocket socket = new DatagramSocket(9998);
        //2、将需要发送的数据,封装到DatagramPacket对象当中
        byte[] data = "hello 明天吃火锅~".getBytes();
        //说明参数:需要封装的对象,对象的长度,主机IP,端口号
        DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),9999);
        socket.send(datagramPacket);
        System.out.println("发送端B发送了数据给接收端A");
        //3、接收接收端发回来的信息
        byte[]  buf = new byte[1024];
        datagramPacket = new DatagramPacket(buf, buf.length);
        //有数据就会接收数据,没有数据就会等待
        socket.receive(datagramPacket);
        //进行拆包
        int lenth = datagramPacket.getLength();
        data = datagramPacket.getData();        //获取到数据
        System.out.println(datagramPacket);
        System.out.println(new String(data, 0, lenth));

        //关闭资源
        socket.close();
        System.out.println("B端退出");
    }
}
04-12 09:24