Java-网络编程

网络通信三要素

什么是网络编程?

  • 网络编程可以让程序与网络上的其他设备中的程序进行数据的交互

网络通信的基本模式

  • 常见的通信模式有如下两种形式:Client-Service(CS)、Browser-Service(BS)
  •  

实现网络编程的三要素

  • IP地址:设备在网络中的地址,是唯一的标识。
  • 端口:应用程序在设备中的唯一标识。
  • 协议:数据在网络中传输的规则。常见的有UDP协议和TCP协议。

IP地址

  • IP(Internet Protocol):全程“互联网协议地址”,是分配给上网设备的唯一标识。
  • 常见的IP分类为IPv4和IPv6
  • IPv6:128位(16个字节),号称可以为地球的每一粒沙子编号。
  • Ipv6分成8个整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开
  •  

 IP地址的形式:

  • 公网地址、私有地址(局域网使用)
  • 192.168.开头就是常见的局域网地址,范围为192.168.0.0---192.168.255.255,专门为组织机构使用。

IP常用的命令

  • ipconfig:查看本机ip地址
  • ping IP地址:检查网络是否连通

特殊IP地址

  • 本机IP:127.0.0.1或者localhost:称为送回地址也可称为本地回环地址,只会寻找当前所在本机

InetAddress的使用

此类表示Interne协议(IP)地址

InetAddress的API如下

名称说明
public static InetAddress getLocalHost()返回本机的地址对象
public static InetAddress getByName(String host)返回指定主机的IP地址对象,参数是域名或者ip地址
public String getHostName()获取此IP地址的主机名
public String getHostAddress()返回IP地址字符串
public boolean isReachable(int timeout)在指定毫秒内连通该IP地址对应的主机,联通成功返回true

IP地址的代表类是:InetAddress类

获取本机对象:public static InetAddress getLocalhost()

端口号

  • 端口号:标识正在计算机设备上运行的进程(程序),被规定为一个16位的二进制,范围是0-65535

端口类型

  • 周知端口:0-1023,被预先定义的知名应用占用(如:HTTP占用:80、FTP占用:21)
  • 注册端口:1024-49151,分配给用户进程或者某些应用程序。(Tomcat占用8080、MySQL占用3306)
  • 动态端口号:49152-65535,之所以被称为动态端口号,是因为它一般不固定分配某些进程,而是动态分配

注意:我们自己开发的程序选择注册端口号,且一个设备不能出现两个程序的端口号一样,否则出错

网络通信协议有两套参考模型

  • OSI参考模型:世界互联协议标准,全球通信规范,由于此模型过于理想化,未能在互联网上广泛的推行
  • TCP/IP参考模型:实际上的国际标准
OSI参考模型TCP/IP参考模型各层对应面向操作
应用程应用层HTTP、FTP、DNS、SMTP...应用程序需要关注的:浏览器、邮箱。程序员一般在此层进行开发
表示层
会话层
传输层传输层TCP、UDP选择使用TCP、UDP协议
网络层网络层IP、ICMP...封装源和目标IP,进行路径选择
数据链路层数据链路层+物理层物理寻址、比特流物理设备中传输
物理层

传输层的2个常见协议

  • TCP(Transmission Control Protocol):传输控制协议
  • UDP(User Datagram Protocol):用户数据协议

TCP协议特点

  • 使用TCP协议,必须双方先建立连接,它是一种面向连接的可靠通信协议。
  • 传输前,采用“三次握手”方式建立连接,所以是可靠的。
  • 在连接中可进行大数据量的传输
  • 连接、发送数据都需要确认,且传输完毕之后,还需要释放已建立的连接,通信效率较低。

TCP协议通信场景

  • 对信息安全要求较高的场景,例如:文件下载、金融等数据通信。

TCP的三次握手建立连接

 TCP的四次挥手断开连接

 UDP协议:

  • UDP是一种无连接、不可靠传输的协议。
  • 将数据源IP、目的地IP和端口封装成数据包,不需要建立连接
  • 将每个数据包大小限制在64KB内
  • 发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
  • 可以广播发送,发送数据结束时无需释放资源,开销小,速度快。

UDP协议通信场景

  • 语音通话、视频通话等

通信协议是什么?

  • 计算机网络中,连接和通信数据的规则被称为网络通信协议

UDP通信

UDP通信:快速入门

DatagramPacket:数据包对象
构造器说明
public DatagramPacket(byte[] buf, int length, InetAddress address, int port)

创建发送端数据包对象

buf:要发送的内容,字节数组

length:要发送内容的字节长度

address:接收端的ip地址

port:接收端的端口号

public DatagramPacket(byte[] buf, int length)

创建发送端数据包对象

buf:用来存储接收的内容

length:能够接收内容的字节长度

DatagramSocket:发送端和接收端对象

构造器说明
public void send(DAatagramPacket dp)发送数据包
public void receive(DatagramPacket p)接收数据包

使用UDP通信实现:发送消息、接收消息

需求:客户端实现步骤

  1. 创建DatagramSocket对象(发送端对象)
  2. 创建DatagramPacket对象封装需要发送的数据(数据包对象)
  3. 使用DatagramSocket对象的send方法传入DatagramPacket对象
  4. 释放资源

UDP通信:多发多收

需求:客户端实现步骤

  1. 创建DatagramSocket对象(发送端对象)
  2. 使用while死循环不断接受用户的数据输入,如果用户输入exit则退出程序
  3. 如果用户输入的不是exit,吧数据封装成DatagramPacket
  4. 使用DatagramSocket对象的send方法将数据包对象进行发送
  5. 释放资源

接收端实现步骤:

  1. 创建DatagramSocket对象并指定端口(端口接收对象)
  2. 创建DatagramPacket对象接收数据(数据包对象)
  3. 使用while死循环不断进行第一次
  4. 使用DatagramSocket对象的receive方法传入DatagramPacket对象

UDP的接收端为什么可以接收数据包,无所谓是哪个发送端的数据包

UDP通信-广播、组播

UDP的三种通信方式

  • 单播:单台主机与单台主机之间的通信
  • 广播:当前主机与所在网络中所有主机通信
  • 组播:当前主机与选定的一组主机的通信

UDP如何实现广播

  • 使用广播地址:255.255.255.255
  • 发送端发送的数据包的目的地写的是广播地址、且指定端口。(255.255.255.255,9999)
  • 本机所在网段的其他主机的程序只要匹配端口成功即可收到消息(9999)

UDP如何实现组播

  • 使用组播地址:224.0.0.0 ~ 239.255.255.255
  • 发送端的数据包的目的地是组播IP(例如:224.0.0.1,端口:9999)
  • 接收端必须绑定该组播IP(224.0.0.1),端口还要对应发送端的目的端口9999,这样即可接收该组播消息
  • DatagramSock的子类MulticastSocket可以在接收端绑定组播IP

TCP通信快速入门

编写客户端代码

在Java中只要是使用java.net.Socket的类实现通信,底层即使用了TCP协议

客户端数据发送消息

客户端实现步骤

  1. 创建客户端的Socket对象,请求与服务端连接
  2. 使用socket对象调用getOutputStream()方法得到字节输出流
  3. 使用字节输出流完成数据的发送
  4. 释放资源:关闭socket管道

什么是线程通信、如何实现

  • 所谓线程通信就是线程间相互发送数据,线程通信通常通过共享一个数据的方式实现
  • 线程间会根据共享数据的情况决定自己该怎么做,以及通知其他线程应该怎么做

线程通信常见模型

  • 生产者与消费者模型:生产者线程负责生产数据,消费者线程负责消费数据
  • 要求:生产者线程生产数据后,唤醒消费者,然后等待自己‘消费者消费完该数据后,唤醒生产者,然后等待自己

步骤:客户端发送数据

  1. 创建客户端的Socket对象,请求与服务端的连接
  2. 使用socket对象调用getOutputStream()方法得到字节输出流
  3. 使用字节输出流完成数据的发送
  4. 释放资源:关闭socket管道

Tcp通信的客户端的代表类是谁?

  • socket类
  • public Socket(String host ,int port)
ServerSocket(服务端)
构造器说明
public ServerSocket(int port)注册服务端口
ServerSocket类成员方法
方法说明
public Socket accept()

等待接收客户端的Socket通信连接

连接成功返回Socket对象与客户端建立端到端的通信

TCP通信服务端用的代表类?

  • ServerSocket类,注册端口
  • 调用accept()方法阻塞等待接收客户端连接,得到Socket对象

TCP通信的基本原理?

  • 客户端怎么发,服务端就怎么收
  • 客户端如果没有消息,服务端会进入阻塞等待
  • Socket一方关闭或者出现异常,对方Socket也会失效或者出错

TCP通信-多发多收消息

需求:使用TCP通信方式实现:多发多收消息

  1. 可以使用死循环控制服务端收完消息继续等待接收下一个消息
  2. 客户端可以使用死循环等待用户不断输入消息
  3. 客户端一旦使用exit,关闭客户端程序,并释放资源

注意:一个线程只能与一个客户端进行通信

多发多收如何实现?

  • 客户端使用循环反复分发送消息
  • 服务端使用循环反复的接收消息

TCP通信-同时接收多个客户端消息

实现服务端接收多个客户端的消息

  • 主线程定义了循环负责接收客户端Socket管道连接
  • 每接收到一个Socket通信管道后分配一个独立的线程负责处理它

创建三个类:服务端(ServerDome1)、客户端(ClientDome)、子线程(ServerReaderThread)

服务端(ServerDome1)

public class ServerDome1 {
    public static void main(String[] args) {
        try {
            System.out.println("=====服务端开启成功=====");
            // 1.注册端口
            ServerSocket serverSocket = new ServerSocket(7777);

            // 2.定义一个死循环,由主线程不断的接收客户端socket管道对象
            while (true){
                // 2.每接受一个客户端socket管道对象交给一个独立的线程去处理
                Socket socket = serverSocket.accept();
                // 3.开始创建独立线程处理socket
                new ServerReaderThread(socket).start();
            }



        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 客户端(ClientDome)

public class ClientDome {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1",7777);

            //从socket管道对象中获取一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //把低级流转换成高级流
            PrintStream ps = new PrintStream(os);

            Scanner sc = new Scanner(System.in);
            while (true){
                System.out.println("请说:");
                String msg = sc.nextLine();
                //发送消息
                ps.println(msg);
                ps.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

子线程(ServerReaderThread)

public class ServerReaderThread extends Thread {
    private Socket socket;
    //定义有参构造,接收传过来的socket对象
    public ServerReaderThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            //从socket管道中得到一个字节输入流
            InputStream inputStream= socket.getInputStream();
            //把字节输入流转换成缓冲字符输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            //按照行读取消息
            String msg;
            while ((msg = br.readLine()) !=null){
                System.out.println(socket.getInetAddress()+"说了:" + msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

TCP通信-使用线程池优化

以上的通信架构存在问题:

  • 客户端与服务端的线程模型是N-N的关系
  • 客户端并发越多,系统瘫痪的越快
public class ServerDome1 {
    //使用静态变量记住一个线程池对象
    private static ExecutorService pool = new ThreadPoolExecutor(3, 5, 6,
            TimeUnit.SECONDS, new ArrayBlockingQueue<>(2),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        try {
            System.out.println("=====服务端开启成功=====");
            // 1.注册端口
            ServerSocket serverSocket = new ServerSocket(7777);

            // 2.定义一个死循环,由主线程不断的接收客户端socket管道对象
            while (true){
                // 2.每接受一个客户端socket管道对象交给一个独立的线程去处理
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress()+"他来了,他上线了");
                //将接收到的socket封装成任务对象,交给线程池排队
                //任务对象负责读取消息
                Runnable target = new ServerReaderRunnable(socket);
                pool.execute(target);

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 线程池的优势:

  • 服务端可以复用线程处理多个客户端,可以避免系统的瘫痪
  • 适合客户端通信时长较短的场景

TCP通信实战案例-即时通信

即时通信的含义,要实现怎么设计:

  • 即时通信是指一个客户端的消息发送出去,其他客户端都可以接收到
  • 之前消息都是发送给服务端的
  • 即时通信需要进行端口转发的设计思想

即时通信的含义,要实现怎么样的设计

  • 即时通信是指一个客户端的消息发出去,其他客户端可以接收到
  • 即时通信需要进行端口转发的设计思想
  • 服务端需要把在线的Socket管道存储起来
  • 一旦收到一个消息要推送给其他管道 

 

TCP实战案例-模拟BS系统

之前客户端都是cs架构,客户端实现需要自己开发实现

BS架构是浏览器访问服务端,不需要开发客户端

TCP通信如何实现BS请求网页信息回来呢?

  • 客户端使用浏览器发起请求(不需要开发客户端)
  • 服务端必须按照浏览器的协议规则响应数据
  • 浏览器使用http协议规则 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值