IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> JavaSE——基础知识回顾18之网络编程部分 -> 正文阅读

[网络协议]JavaSE——基础知识回顾18之网络编程部分

文章目录



前言

Java中的网络编程已经是属于JavaSE部分的尾声内容了,这一周剩下的还有一个反射的内容。都属于理论性与操作性较强的部分,如果内容错误欢迎留言指点


以下是本篇文章正文内容,下面案例可供参考

一、什么是网络编程

(1)计算机网络

内容:所谓计算机网络,是指将空间上具有独立功能的多台计算机以及它的外部设备(例如路由器等),通过通信线路连接起来,在网络操作系统,网络管理软件以及网络通信协议的管理下,实现资源共享和信息传递的计算机系统。

(2)网络编程

实现多态计算机之间数据共享与传递,网络应用程序主要组成是:网络编程+IO流+多线程

(3) 网络三要素与三大协议

3.1网络三要素

网络通讯模型:请求(客户端)—》响应请求(服务端)
内容:网络三大要素为:IP地址 、 端口号(port)、 网络协议(数据传输的规则)
IP地址:网络中计算机的唯一标识(IP地址是一个32位的二进制数据,为了方便,将一个字节的二进制转换为一个十进制的数据),IP地址的组成=网络号段+主机段(IPV4是32位,IPV6是128位,我们的计算机通常是IPV4,本机的IP地址都是“127.0.0.1”);
端口号:每一个网络程序都至少一个端口号,这是用于标示进程的逻辑地址,不同的地址其端口号标示不同,有效端口号范围:0 ~ 65535,其中0 ~ 1024是系统使用或保留端口
网络协议:都是数据传输的规则,TCP 、UDP都是传输层的协议(后面会详细介绍)

3.2网络三大协议

TCP:
UDP:
Http:

(3)套接字“Socket”的使用

套接字的内容:如果要具体讲的话他就有点烧脑了,我们就简单提一下它的功能,Socket是将网络三大要素中的 IP 和 端口号 打包成了一个内容使得计算机之间的交流更加简单便利,Scoket也叫套接字,其表示的是IP地址和端口号的组合。网络编程主要就是指Socket编程,网络间的通信其实就是Socket间的通信,数据就通过IO流在两个Scoket间进行传递。

二、三大协议的使用步骤与操作案例

(1)TCP协议(面向连接的协议,可靠性更高)

内容:三次握手,四次挥手类似于打电话
理解图如下:
在这里插入图片描述

(2)UDP协议(无连接的协议)

内容:单方面发送消息数据包,类似于发快递。
特点:容易造成数据丢失,故此常应用于视频聊天,相比较于TCP它更显得不负责任,此外UDP没有服务端,只有客户端即直接行驶的是用户之间的交流没有服务端的介入。

(3)TCP VS UDP

在这里插入图片描述

(4)HTTP协议

三、实战案例:实现不同用户之间的聊天

(1)TCP案例部分:

1.1一对一聊天

说明:实现一对一聊天需要用到线程的知识,为了能够使得客户端与服务端之间的交流能够顺利创建一个接收的线程

客户端(Client)代码如下:

import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    /**
     * 需求:优化一对一聊天
     */
    public static void main(String[] args) throws Exception {
        Socket socket=new Socket("127.0.0.1",8080);
        Scanner input=new Scanner(System.in);
        new ReceiveThread(socket).start();

        PrintStream ps=new PrintStream(socket.getOutputStream());

        while (true){
            ps.println("雍仲:"+input.next());
        }

    }
}

服务端(Server):

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    public static void main(String[] args) throws Exception {
        //创建服务端
        ServerSocket serverSocket = new ServerSocket(8080);
        Socket socket=serverSocket.accept();//由服务端创建一个 服务于客户端的Socket
        Scanner input=new Scanner(System.in);
        //向服务端发送消息
        new ReceiveThread(socket).start();
        PrintStream ps=new PrintStream(socket.getOutputStream());

        while (true){
            ps.println("中国人寿保险:"+input.next());
        }
    }
}

线程接受器


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ReceiveThread extends Thread{
    private Socket socket;
    public ReceiveThread(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        BufferedReader bufferedReader=null;
        try {
            bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (true){
            String readLine=null;
            try {
                 readLine=bufferedReader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(readLine);
        }
    }
}

1.2实现文件的传输(不正经系列)

这个案例的要求的实现主要是依靠对输入流以及输出流的熟练使用,以及通过对网络编程Socket的熟练使用

Client客户端


import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    /**
     * 需求:传输文件
     */
    public static void main(String[] args) throws Exception {
        Socket socket=new Socket("127.0.0.1",8080);

        //1、创建流对象
        FileInputStream fis=new FileInputStream("明日花绮罗.jpg");
        OutputStream out=socket.getOutputStream();//将该内容发送到服务端 127.0.0.1


        //2、读写数据
        int len;
        byte [] bs=new byte[1024];
        while ((len=fis.read(bs))!=-1){
            out.write(bs,0,len);
        }
        //3、关闭流对象
        fis.close();
        out.close();
    }
}

Server服务端类:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket=new ServerSocket(8080);
        Socket socket=serverSocket.accept();//接收客户端的消息的Socket
        //1、创建流对象
        InputStream is=socket.getInputStream();//利用服务端的Socket来进行接受客户端的传输内容,相当于 这代码就是客户端中的FileInputStream fis=new FileInputStream("明日花绮罗.jpg")
        OutputStream os=new FileOutputStream("download.jpg");
        //2、读写数据
        int len;
        byte [] bs=new byte[1024];
        while ((len=is.read(bs))!=-1){
            os.write(bs,0,len);
        }
        //3、关闭流对象
        os.close();
        is.close();
    }
}

结果展示:
在这里插入图片描述

1.3多人之间聊天

说明 :对于实现多人聊天,我们需要注意的一点就是在我们不知道到底有多少个用户在聊天的时候我们就无法确定有多少个客户端Socket,因此就不能在服务端中明确创建多少个服务端的Socket来进行对象之间的匹配,因此我们需要用到多线程,而谈及多线程的话明显是要实现多个用户的交流,而对于这一部分我们作为服务器的控制者,那么我们就需要收集到所有用户的IP地址和Socket来进行他们之间的消息收集和发送到其余的用户那儿去故此 我们需要用到一个Map,而这个Map就是多线程下的安全性最高的ConcurrenHashMap。

创建用户端类(Client)

import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
    /**
     * 需求 :实现群聊
     */
    public static void main(String[] args) throws Exception{
        Socket socket=new Socket("127.0.0.1",8080);
        Scanner input=new Scanner(System.in);
        new ReceiveThread(socket).start();
        PrintStream ps=new PrintStream(socket.getOutputStream());
        while (true){
            ps.println("雍仲杨:"+input.next());
        }
    }
}

创建服务端类(Server)


import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;

public class Server {
    //这里设置一个静态公共Map用来存放所有的客户端的Socket与其ip地址
    public static ConcurrentHashMap<InetAddress,Socket> map=new ConcurrentHashMap<>();
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket=new ServerSocket(8080);

        //由于是多个用户之间的聊天 因此在不确定有多少个用户的时候就无法知道有多少个用户的Socket,故此我们选择用一个死循环来创建服务端的SOcket来匹配与值数量的用户Socket
        while (true){
            Socket socket=serverSocket.accept();

            //获取客户端的IP地址
            InetAddress ip=socket.getInetAddress();
            //存放IP与对应的Socket
            map.put(ip,socket);
            //创建线程并启动线程
            new ServerThread(socket).start();

        }
    }
}

创建接受线程类(ReceiveThread)


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class ReceiveThread extends Thread{
    private Socket socket;

    public ReceiveThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br=null;
        try {
            br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (true){
            String readLine=null;

            try {
                readLine=br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(readLine);
        }
    }
}

创建服务线程类(ServerThread)


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class ServerThread extends Thread{
    private Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        //接收当前Socket的消息
        BufferedReader bufferedReader = null;
        try {
             bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (true){
            String readLine=null;
            try {
                readLine =bufferedReader.readLine();
                System.out.println(readLine);
                //发送给其他的Socket
                ConcurrentHashMap<InetAddress,Socket> map=Server.map;

                Set<Entry<InetAddress,Socket>> entrySet=map.entrySet();
                for (Entry<InetAddress,Socket> entry:entrySet) {
                    InetAddress key=entry.getKey();
                    Socket value=entry.getValue();

                    if (socket.getInetAddress()!=key){//这句代码的意思是,如果当前的key不等于当前的socket那么说明就是等于其余的socket
                        PrintStream ps=new PrintStream(value.getOutputStream());
                        ps.println(readLine);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

(2)UDP部分案例:

2.1通过用户之间的发送快递的形式来解释

创建第一个用户端


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

public class Client01 {
    public static void main(String[] args) throws IOException {
        /**
         * 知识点:UDP协议
         */
        //发送者所在城市的快递公司,发送者不需要写端口号
        DatagramSocket socket=new DatagramSocket();
        //发送礼物者发快递
        //礼物
        byte [] bs="鲜花一束~~~".getBytes();
        //数据包--快递包裹
        DatagramPacket packet=new DatagramPacket(bs,bs.length, InetAddress.getByName("127.0.0.1"),8080);
        //发送快递
        socket.send(packet);

        //4、接受 用户端2 的礼物
        byte [] buf=new byte[1024];
        packet=new DatagramPacket(buf, buf.length);
        socket.receive(packet);
        System.out.println(new String(buf).trim());
    }
}

创建用户端2

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Client02 {
    public static void main(String[] args) throws IOException {
        //接受礼物者
        //接收者所在地的快递公司
        DatagramSocket socket=new DatagramSocket();
        //接受发送者的礼物
        byte [] bs=new byte[1024];
        DatagramPacket packet=new DatagramPacket(bs,bs.length);
        socket.receive(packet);
        System.out.println(new String(bs).trim());
        //3、给 用户端01 回礼
        byte [] buf="典藏版黑金卡".getBytes();
        packet=new DatagramPacket(buf, buf.length,packet.getSocketAddress());
        socket.send(packet);
    }
}

总结

本文主要是通过一些基本理论+实战场景来进行梳理的,内容还不完整,后期我会慢慢进行填补,若所写内容之中有错误请指正。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-30 12:32:49  更:2021-08-30 12:33:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:28:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码