JavaSE之网络编程

网络编程

编写在不同计算机上进行数据传输的程序。

网络编程场景

网络应用程序、即时通信、网游对战、金融证券、国际贸易、邮件等等。

常见的软件架构有如下2种形式:Client-Server(CS) 、 Browser/Server(BS)

Client-Server(CS): 客户端-服务端模式

Browser/Server: 浏览器-服务端模式

网络编程三要素

IP地址

IP地址概念

互联网协议地址(Internet Protocol Address),俗称IP。

IP地址用来给网络中的计算机进行编号

IP地址作用

通过IP地址可以找到网络中的某台电脑

IP地址就相当于生活中的家庭住址

IPv4:是一个32位的二进制数,通常被分为4个字节,表示成 a.b.c.d 的形式,例如 192.168.65.100。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。

IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。有资料显示,全球IPv4地址在2011年2月分配完毕。为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,分成8组以十六进制数显示,表示成 ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。

查看本机IP地址
在DOS命令行输入: ipconfig

检查网络是否连通
在DOS命令行输入: ping IP地址/域名

特殊IP地址
127.0.0.1:是回送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用

端口号

端口介绍

我们一台电脑上会安装很多的应用程序,内网通,微信,QQ。如何找到计算机中的某个程序?

应用程序在设备中唯一的标识。

端口作用

通过端口号可以找到电脑上的某个程序

用两个字节表示的整数,它的取值范围是0~65535。

其中0~1023之间的端口号用于一些知名的网络服务或者应用。

我们自己使用1024以上的端口号就可以了。

协议

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

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

OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推广。

TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

UDP

UDP协议特点: 用户数据报协议(User Datagram Protocol)

不需要连接

速度快

有大小限制一次最多发送64K

易丢失数据

UDP协议通信场景(速度要求高,数据完整性要求不高)

直播

语音通话

视频会话

TCP

TCP协议特点: 传输控制协议 (Transmission Control Protocol)

需要连接

速度慢

没有大小限制

不易丢失数据

TCP协议通信场景(速度要求不高,数据完整性要求高)

下载

扫码支付

金融等数据通信。

编写UDP的接收端

/*
    编写UDP的接收端

    DatagramPacket(byte buf[], int length)
        创建空的数据包
        byte buf[]: 用来保存数据的数组
        int length: 数组一次可以接收多少数据

    注意:要先运行接收端

 */
public class UDPReceiver {
    public static void main(String[] args) throws IOException {
        System.out.println("接收端启动!");
        // 1.创建接收端
        DatagramSocket socket = new DatagramSocket(6666);
        // 2.创建空的数据包
        byte[] b = new byte[1024];
        DatagramPacket packet = new DatagramPacket(b, b.length);
        // 3.接收数据, 接收到的数据放到包中
        socket.receive(packet);
        int length = packet.getLength();
        System.out.println(new String(b,0,length));
        // 4.关闭资源
        socket.close();
    }
}

编写UDP的发送端

/*
	编写UDP的发送端

DatagramPacket(byte buf[], int offset, int length, InetAddress address, int port)
    byte buf[]: 要发送的数据的字节数组
    int offset: 从数组哪个位置开始发
    int length: 发送多少数据
    InetAddress address: 接收方的IP地址
    int port: 接收方的端口

    InetAddress.getLocalHost(): 获取本机的IP
    InetAddress.getByName(""): 别人的IP地址

注意:UDP协议不需要连接,没有接收端也不会报错,数据丢失啦
 */
public class UDPSender {
    public static void main(String[] args) throws IOException {
        System.out.println("发送端启动!");
        byte[] a = "发送".getBytes();
        // 1.创建发送端
        DatagramSocket socket = new DatagramSocket();
        // 2.创建数据包
        DatagramPacket packet = new DatagramPacket(a, 0, a.length, InetAddress.getByName("127.0.0.1"), 6666);
        // 3.发送数据
        socket.send(packet);
        // 4.关闭资源
        socket.close();
    }
}

编写TCP的服务端

public class TCPServer {
    public static void main(String[] args) throws IOException {
        System.out.println("服务端启动啦!");
        // 1.创建TCP服务端
        ServerSocket serverSocket = new ServerSocket(8848);
        // 2.同意客户端的请求, 如果没有客户端连接就一直等
        Socket socket = serverSocket.accept();
        // 3.得到输入流读取数据
        InputStream inputStream = socket.getInputStream();
        byte[] b = new byte[1024];
        int len = inputStream.read(b);
        System.out.println(new String(b,0,len));
        // 4.得到输出流写数据
        OutputStream outputStream = socket.getOutputStream();
        byte[] b1 = "老地方见".getBytes();
        outputStream.write(b1);
        // 5.关闭资源
        outputStream.close();
        inputStream.close();
        serverSocket.close();
    }
}

编写TCP的客户端

/*
目标: 编写TCP客户端

Socket(String host, int port) 创建客户端, 会自动连接服务端
    String host: 服务端的IP
    int port: 服务端的端口

注意:
    TCP协议先启动客户端,没有服务端,会出现连接异常
    TCP程序一定要先运行服务端
 */
public class TCPClient {
    public static void main(String[] args) throws IOException {
        System.out.println("客户端启动啦!");
        // 1.创建客户端
        Socket socket = new Socket("127.0.0.1", 8848);
        // 2.得到输出流写数据
        OutputStream outputStream = socket.getOutputStream();
        byte[] a = "约吗".getBytes();
        outputStream.write(a);
        // 3.得到输入流读取数据
        byte[] b = new byte[1024];
        InputStream inputStream = socket.getInputStream();
        int len = inputStream.read(b);
        System.out.println(new String(b,0,len));
        // 4.关闭资源
        inputStream.close();
        outputStream.close();
        socket.close();
    }
}

文件上传(多线程)

客户端

public class UploadClient1 {
    public static void main(String[] args) {
        System.out.println("客户端启动");
        int i = 0;
        while (i<=20) {
            i++;
            new Thread(()->{
                try {
                    Socket socket = new Socket("127.0.0.1",10086);
                    FileInputStream fis = new FileInputStream("Study_day12\\abc\\1.png");
                    OutputStream outputStream = socket.getOutputStream();
                    int len;
                    byte[] b = new byte[1024*8];
                    while((len = fis.read(b))!=-1){
                        outputStream.write(b,0,len);
                    }
                    System.out.println("上传完了");
                    socket.shutdownOutput();

                    InputStream inputStream = socket.getInputStream();
                    len = inputStream.read(b);
                    System.out.println("客户端收到的:"+new String(b,0,len));
                    outputStream.close();
                    fis.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

UploadRun

public class UploadRun implements Runnable{
    private Socket socket;
    public UploadRun(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run() {

        try {

            // 3.得到Socket输入流
            InputStream inputStream = socket.getInputStream();
            // 4.创建文件输出流
            String s = UUID.randomUUID().toString();
            FileOutputStream fos = new FileOutputStream("Study_day12\\upload\\"+s+".png");
            // 5.循环读写数据
            int len;
            byte[] b = new byte[1024*8];
            //因为这是socket的输入流,是BIO的方式,不会等于-1,只会一直死等,直到别人明确告诉他没人了,不需要等了才会停止
            //所以在客户端加上终止等待
            while((len = inputStream.read(b))!=-1){
                fos.write(b,0,len);
            }
            // 6.得到Socket的输出流写数据
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write("接收完成".getBytes());
            // 7.关闭
            outputStream.close();
            fos.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端

public class UploadServer1 {
    public static void main(String[] args) throws IOException {
        System.out.println("文件上传服务端启动啦!");
        ExecutorService pool = Executors.newFixedThreadPool(10);
        // 1.创建服务端
        ServerSocket serverSocket = new ServerSocket(10086);


        while (true){
            // 2.同意客户端的连接
            Socket socket = serverSocket.accept();
            UploadRun uploadRun = new UploadRun(socket);
            pool.submit(uploadRun);
        }
    }
}

commons-io的使用

public static void main(String[] args) throws IOException {
        // 1.读取文件中内容返回字符串
        String s = FileUtils.readFileToString(new File("Study_day12\\abc\\bw.txt"), "utf8");
        System.out.println(s);

        // 2.复制文件(复制的文件必须存在,复制后的路径不存在会自动生成)
        FileUtils.copyFile(new File("Study_day12\\abc\\bw.txt"),new File("Study_day12\\aaa\\bw.txt"));

        // 3.复制文件夹,放到指定目录下
        FileUtils.copyDirectoryToDirectory(new File(""),new File(""));
    }
}

Junit

/*
Junit的使用步骤:
    1.定义测试方法
    2.在方法上添加@Test注解
    3.运行测试方法

单元测试方法的要求 *****
    1.必须是public修饰
    2.返回值必须是void
    3.不能有参数
    4.不能是静态方法
 */
public class TestFirst {

    @Test
    public void test(){

    }
}
/*
@Before:在每个测试的方法前运行。
@After:在每个测试的方法后运行。
@BeforeClass:在所有测试的方法前运行一次。
@AfterClass:在所有测试的方法后运行一次。

    资源初始化
 */
public class TestSecond {
    @Test
    public void test1(){
        System.out.println("单元测试1");
    }

    @Test
    public void test2(){
        System.out.println("单元测试1");
    }

    //需要加静态
    @BeforeClass
    public static void BeforeClass(){
        System.out.println("BeforeClass");
    }

    @AfterClass
    public static void AfterClass(){
        System.out.println("AfterClass");
    }

    @Before
    public void Before(){
        System.out.println("Before");
    }

    @After
    public void After(){
        System.out.println("After");
    }

}

在这里插入图片描述

NIO

NIO概述

JDK1.4以前: InputStream/OutputStream称为BIO(Blocking IO) 阻塞式IO

JDK1.4推出了一套新的IO体系称为NIO (New IO/ Not Blocking IO) 非阻塞式IO

阻塞、非阻塞概念

阻塞和非阻塞都是处理IO数据的方式

阻塞:如果没有数据就一直等待

非阻塞:如果没有数据,不会一直等待,可以做其他事情

非阻塞的好处,不需要一直等待,当有数据来才需要处理,没有数据可以做其他操作

Channel(通道)可以双向传输数据

ByteBuffer 相当于之前BIO的byte[],可以保存要发送和接收的数据

ByteBuffer 效率比byte[]要高,功能更强大

使用了多路复用,只需要一个线程就可以处理
多个通道,降低内存占用率,减少CPU切换时间,
在高并发、高频段业务环境下有非常重要的优势

NIO服务端:

1.使用Selector多路复用器,监听每个客户端的请求事件。

2.服务端不会阻塞等待某个客户端。

NIO 有对应的框架netty

tomcat服务器底层也是NIO

最后

如果你对本文有疑问,你可以在文章下方对我留言,敬请指正,对于每个留言我都会认真查看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaSE网络编程采用的是基于TCP/IP协议的网络模型。这个模型包括客户端和服务器端两部分。客户端通过套接字(Socket)与服务器建立连接,服务器则监听客户端的连接请求并进行响应。 在Java中,可以使用Socket类和ServerSocket类来实现网络编程。Socket类用于建立客户端与服务器之间的通信连接,而ServerSocket类则用于创建服务器端的套接字,监听并接受客户端的连接请求。 客户端通过创建Socket对象,指定服务器的IP地址和端口号,然后通过Socket对象的方法与服务器进行通信。服务器端通过创建ServerSocket对象,指定服务器要监听的端口号,并通过accept()方法接受客户端的连接请求。一旦建立了连接,客户端和服务器端就可以通过输入流和输出流来进行数据的传输。 网络模型是基于TCP/IP协议的,因此可以使用Java的InputStream和OutputStream来进行数据的读写。客户端可以通过InputStream从服务器端接收数据,通过OutputStream向服务器端发送数据。服务器端则可以通过InputStream接收客户端发送的数据,通过OutputStream向客户端发送数据。 总结来说,JavaSE网络编程采用的是基于TCP/IP协议的网络模型,通过Socket和ServerSocket来实现客户端和服务器端之间的通信。通过InputStream和OutputStream来进行数据的读写。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JavaSE——网络编程](https://blog.csdn.net/yzl1293346757/article/details/126192384)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JavaSE学习——网络编程](https://blog.csdn.net/Demon_and_Angle_/article/details/126387829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值