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 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Java学习笔记day24-网络编程 -> 正文阅读

[网络协议]Java学习笔记day24-网络编程

网络编程

概述
  • 在网络通信协议下,不同计算机上运行的程序,可以进行数据传输
三要素
  • IP地址:设备在网络中的地址,是唯一标识;
  • 端口:应用程序在设备中的唯一标识;
  • 协议:数据在网络传输的规则,常见的协议有UDP协议和TCP协议。
    • UDP协议
      • 用户数据报协议
      • UDP是面向无连接通信协议,速度快,有大小限制一次最多发送64k,数据不安全,易丢失数据。
    • TCP协议
      • 传输控制协议
      • TCP协议是面向连接的通信协议,速度慢,没有大小限制,数据安全。
IP地址

常用命令:

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

特殊IP地址:

  • 127.0.0.1:是会送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
InetAddress
  • static InetAddress getByName(String host) :确定主机名称的IP地址,主机名称可以是机器名称,也可以是IP地址
  • String getHostName() :获取此IP地址的主机名
  • String getHostAddress() :返回文本显示中的IP地址字符串
import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressTest {
    public static void main(String[] args) throws UnknownHostException {
        InetAddress address = InetAddress.getByName("我也会飞啦");
        String hostName = address.getHostName();
        System.out.println("主机名为:"+hostName);
        String hostAddress = address.getHostAddress();
        System.out.println("IP为:"+hostAddress);
    }
}
端口

端口号:用两个字节表示的整数,它的取值范围是065535。其中01023之间的端口号用于一些知名的网络服务或者应用。我们自己使用1024以上的端口号就可以了。一个端口号只能被一个应用程序使用

UDP发送数据

举个栗子:发送礼物

  1. 找菜鸟驿站-----------创建发送端的DatagramSocket对象
  2. 打包礼物-----------创建数据,并把数据打包(DatagramPacket)
  3. 由驿站发送包裹------------调用DatagramSocket对象的方法发送数据
  4. 付钱走人-------------释放资源
import java.io.IOException;
import java.net.*;

public class ClientTest {
    public static void main(String[] args) throws IOException {
        //找驿站
        DatagramSocket ds = new DatagramSocket();
        //打包礼物
        String s = "送给挚爱的人的礼物";
        byte[] bytes = s.getBytes();
        InetAddress address = InetAddress.getByName("127.0.0.1");
        int port = 8888;
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
        //发送包裹
        ds.send(dp);
        //付钱走人
        ds.close();
    }
}
UDP接收数据
  1. 找接收点-------------创建接收端的DatagramSocket对象
  2. 找新箱子-------------创建一个箱子用于接收数据
  3. 接收礼物并放回箱子中--------------调用DatagramSocket的方法接收数据并放入箱子中
  4. 从箱子里获取礼物---------------解析数据包,并把数据放在控制台显示
  5. 拿完走人---------------释放资源
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        //找接收点,参数表示接收端从8888端口接收数据
        DatagramSocket ds = new DatagramSocket(8888);
        //创建一个新的箱子
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
        //把礼物放到新箱子中
        ds.receive(dp);
        //从新的箱子里获取礼物
        //byte[] data = dp.getData();
        int length = dp.getLength();
        System.out.println(new String(bytes,0,length));
        //拿完走人
        ds.close();
    }
}
UDP通信程序练习

按照下面的要求实现程序

  1. UDP发送数据:数据来自于键盘录入,直到输入的数据是回见,发送数据结束
  2. UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
发送端
import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class ClientTest {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        DatagramSocket ds = new DatagramSocket();
        while (true) {
            String s = sc.nextLine();
            if(s.equals("回见")){
                break;
            }
            byte[] bytes = s.getBytes();
            InetAddress address = InetAddress.getByName("127.0.0.1");
            int port = 8888;
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
            ds.send(dp);
        }
        ds.close();
    }
}

接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(8888);
        while (true) {
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
            ds.receive(dp);
            byte[] data = dp.getData();
            int length = dp.getLength();
            System.out.println(new String(data,0,length));
        }
        //ds.close();
    }
}
UDP的三种通信方式
  • 单播:点对点通信
  • 组播:一个发送端通过路由器将数据发送给一组接收端
  • 广播:一个发送端通过路由器将数据发送给局域网中的所有接收端
UDP通信组播

组播地址:224.0.0.0239.255.255.255,其中224.0.0.0224.0.0.255位预留的组播地址

发送端
import java.io.IOException;
import java.net.*;

public class clientTest {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();
        String s = "hello组播";
        byte[] bytes = s.getBytes();
        InetAddress address = InetAddress.getByName("224.0.2.0");
        int port = 8888;
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
        ds.send(dp);
        ds.close();
    }
}

接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket(8888);
        DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
        //把当前计算机绑定一个组播地址,表示添加到这一组中
        ms.joinGroup(InetAddress.getByName("224.0.2.0"));
        ms.receive(dp);
        byte[] data = dp.getData();
        int length = dp.getLength();
        System.out.println(new String(data,0,length));
        ms.close();
    }
}
UDP通信广播

广播地址:255.255.255.255

发送端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class ClientTest {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();
        String s = "嘘!";
        byte[] bytes = s.getBytes();
        InetAddress address = InetAddress.getByName("255.255.255.255");
        int port = 8888;
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
        ds.send(dp);
        ds.close();
    }
}
接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(8888);
        DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
        ds.receive(dp);
        byte[] data = dp.getData();
        int length = dp.getLength();
        System.out.println(new String(data,0,length));
        ds.close();
    }
}
TCP通信原理

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象;

通信之前要保证连接已经建立,通过Socket产生IO流来进行网络通信。

TCP发送数据的步骤
  1. 创建客户端的Socket对象(Socket)与指定服务端连接 Socket(String host,int port)
  2. 获取输出流,写数据OutputStream getOutputStream()
  3. 释放资源void close()
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class ClientTest {
    public static void main(String[] args) throws IOException {
        //创建一个Socket对象
        Socket socket = new Socket("127.0.0.1",8888);
        //获取一份IO流开始写数据
        OutputStream os = socket.getOutputStream();
        os.write("hello".getBytes());
        //释放资源
        os.close();
        socket.close();
    }
}
TCP接收数据
  1. 创建服务器端的Socket对象(ServerSocket) ServerSocket(int port)
  2. 监听客户端连接,返回一个Socket对象 Socket accept()
  3. 获取输入流,读数据,并把数据显示在控制台 InputStream getInputStream()
  4. 释放资源 void close()
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        //创建Socket对象
        ServerSocket ss = new ServerSocket(8888);
        //等待客户端连接
        Socket accept = ss.accept();
        //获得输入流对象
        InputStream is = accept.getInputStream();
        int b;
        while ((b = is.read()) != -1){
            System.out.println((char) b);
        }
        //释放资源
        is.close();
        ss.close();
    }
}

注意

  • accept方法是阻塞的,作用就是等待客户端连接;
  • 客户端创建对象并连接服务器,此时是通过三次握手协议保证跟服务器之间的连接;
  • 针对客户端来讲是往外写的,所以是输出流;针对服务器来讲是往里读的,所以是输入流;
  • read方法也是阻塞的;
  • 在关流的时候,还多了一个网服务器写结束标记的动作;
  • 最后一次断开连接,通过四次挥手协议保证连接终止;
三此握手

image-20220225014629103

四次挥手

image-20220225014717012

TCP练习1
  • 客户端:发送数据,接收服务器反馈
  • 服务器:接收数据,给出反馈
发送端
import java.io.*;
import java.net.Socket;

public class ClientTest {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",8888);
        OutputStream os = socket.getOutputStream();
        os.write("hello".getBytes());
        //os.close;如果在这里关流,会导致整个socket都无法使用
        socket.shutdownOutput();//紧紧关闭输出流,并写一个结束标记,对socket没有任何影响

//        InputStream is = socket.getInputStream();
//        int b;
//        while ((b = is.read()) != -1){
//            System.out.println((char) b);
//        }
//        is.close();
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        br.close();
        os.close();
        socket.close();
    }
}

接收端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8888);
        Socket accept = ss.accept();
        InputStream is = accept.getInputStream();
        int b;
        while ((b = is.read()) != -1){
            System.out.println((char) b);
        }
//        OutputStream os = accept.getOutputStream();
//        os.write("你是谁?".getBytes());
//        os.close();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bw.write("你是谁?");
        bw.newLine();
        bw.flush();
        bw.close();
        is.close();
        accept.close();
        ss.close();
    }
}
TCP练习2
  • 客户端:将本地文件上传到服务器,接收服务器的反馈
  • 服务器:接收客户端上传的文件,上传完毕之后给出反馈。
客户端
import java.io.*;
import java.net.Socket;

public class ClientTest {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",8888);
        //本地流,用来读取本地文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day24\\1.gif"));
        //写到服务器,网络中的流
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        int b;
        while ((b = bis.read())!=-1){
            bos.write(b);//通过网络写到服务器中
        }
        //给服务器一个结束标记
        socket.shutdownOutput();

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line;
        while ((line = br.readLine())!=null){
            System.out.println(line);
        }
        bis.close();
        socket.close();
    }
}

服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8888);
        Socket accept = ss.accept();
        //网络中的流,从客户端读取数据
        BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
        //本地的IO流,把数据写到本地,实现永久化存储
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day24\\2.gif"));
        int b;
        while ((b = bis.read())!=-1){
            bos.write(b);
        }
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bw.write("上传成功");
        bw.newLine();
        bw.flush();

        bos.close();
        accept.close();
        ss.close();
    }
}
UUID

该类可以生成唯一且随机的字符串;

import java.util.UUID;

public class UUIDTest {
    public static void main(String[] args) {
        UUID uuid = UUID.randomUUID();
        String s = uuid.toString().replace("-","");
        System.out.println(s);
    }
}
利用循环和UUID对练习2进行优化
只改动服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8888);
        Socket accept = null;
        while (true) {
            accept = ss.accept();
            //网络中的流,从客户端读取数据
            BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
            //本地的IO流,把数据写到本地,实现永久化存储
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day24\\"+ UUID.randomUUID().toString().replace("-","")+".gif"));
            int b;
            while ((b = bis.read())!=-1){
                bos.write(b);
            }
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
            bw.write("上传成功");
            bw.newLine();
            bw.flush();

            bos.close();
            accept.close();
        }
        //ss.close();
    }
多线程+线程池进一步优化练习2
线程:
import java.io.*;
import java.net.Socket;
import java.util.UUID;

public class ThreadSockt implements Runnable {
    private Socket accept;
    public ThreadSockt(Socket accept) {
        this.accept = accept;
    }

    @Override
    public void run() {
        BufferedOutputStream bos = null;
        try {
            //网络中的流,从客户端读取数据
            BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
            //本地的IO流,把数据写到本地,实现永久化存储
            bos = new BufferedOutputStream(new FileOutputStream("day24\\"+ UUID.randomUUID().toString().replace("-","")+".gif"));
            int b;
            while ((b = bis.read())!=-1){
                bos.write(b);
            }
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
            bw.write("上传成功");
            bw.newLine();
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (bos !=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (accept != null){
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

只改进服务器端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ServerTest {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8888);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,8,60, TimeUnit.SECONDS,new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        Socket accept = null;
        while (true) {
            accept = ss.accept();
            ThreadSockt ts = new ThreadSockt(accept);
            //new Thread(ts).start();
            threadPoolExecutor.submit(ts);
        }
        //ss.close();
    }
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 12:07:35  更:2022-02-26 12:11:24 
 
开发: 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/26 7:47:23-

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