---
url: /notes/java-se/网络编程/index.md
---
# 网络编程

# 软件架构

B/S：`Brower/Server`结构，指的是浏览器和服务器结构

C/S：`Client/Server`结构，指的是客户端和服务器结构

![image-20211124225043389](https://note-1259190304.cos.ap-chengdu.myqcloud.com/note/image-20211124225043389.png)

`IP地址`:互联网协议地址，ip地址是给网络中的计算机设备做唯一的编号

`IPV4`:是一个32为二进制数，通常是四个字节，表现形式a.b.c.d每一个单词的取值范围0-255之间，总的范围为42亿个

`IPV6`:为了扩大地址空间，决定采用IPV6重新定义地址空间，采用128位地址长度16个字节，分成8组16进制数ABCD:EF01:2345:6789:ABCD:EF01:2345:6789可以为地球上的每一-粒沙子定义地址
本机ip地址特殊写法: 127.0.0.1   localhost

**端口号** :就是设备中进程的唯一标识。采用两个字节标识的整数，它的取值范围0-65535

其中0-1023这些端口已经被征用了，常规的都是1024往后定义

同一台机器不能出现两个相同端口号的程序

![image-20211124225100105](https://note-1259190304.cos.ap-chengdu.myqcloud.com/note/image-20211124225100105.png)

# 网络通信协议

计算机通信必须要遵守的协议，协议中规定了数据的传输格式，传输速率，传输步骤；双方必须同时遵守，才能进行数据交换

## TCP/IP

是互联网中最广泛的协议，它定义了计算机如何连入互联网，以及数据如何在它们之间进行传输的标准。**面向连接的协议** 。在传输数据之前，在发送端和接收端建立逻辑联系，再传输数据，提供了两台计算机之间可靠无差错的数据传输。日常使用：浏览器，下载

### 三次握手

## UDP

用户数据报协议，是一个**面向无连接的协议** 。
传输数据时不需要建立连接，不管对方服务是否启动，直接将数据、数据源和目的地都封装到数据包中，直接发送
传输速度快，容易丢包。
常用于视频会议

# Socket

`public class Socket extends Object implements Closeable`
该类实现客户端套接字（也称为“套接字”）。 套接字是两台机器之间通信的端点。
其中还包含IP地址和端口号的网络单位

## 构造方法

`public Socket(String host, int port)`
创建流套接字并将其连接到指定主机上的指定端口号。
`host：服务器的IP地址`
`port：服务器的端口号`
如果指定的主机是`null` ，则相当于将地址指定为`InetAddress.getByName(null)` 。 换句话说，它等同于指定环回接口的地址。

## 成员方法

`public OutputStream getOutputStream() `
返回此套接字的输出流。
`public InputStream getInputStream() `
返回此套接字的输入流。
`public void close() `
关闭此套接字。

## 实现步骤

1. 创建一个`客户端对象Socket`，构造方法中绑定服务器的**IP地址** 和**端口号**

2. 使用Socket对象中的`getOutputStream`获取网络字节输出流对象OutputStream

3. 使用OutputStream对象的`write()`方法，将给服务器数据发送

4. 使用Socket对象的`getInputStream`，获取网络字节输入流对象InputStream

5. 使用InputStream的`read()`方法，读取服务器发回的数据

6. 关闭流，释放资源

```java
package com.ntework.demo1;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * @Description tcp通信的客户端，向服务器发送连接请求
 * @Classname Client
 * @Date 2021/8/18 10:42
 * @Created by 折腾的小飞
 */
public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 2000);
        OutputStream os = socket.getOutputStream();
        os.write("客户端发送".getBytes());

        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len;
        while ((len=is.read(bytes))!=-1){
            System.out.println(new String(bytes, 0, len));
        }

        socket.close();
    }
}

```

# ServerSocket

`public class ServerSocket extends Object implements Closeable`
该类实现服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行某些操作，然后可能将结果返回给请求者。

## 构造方法

`public ServerSocket(int port)`
创建绑定到指定端口的服务器套接字。
端口号`0`表示端口号自动分配，通常来自临时端口范围。 然后可以通过调用`getLocalPort`来检索此端口号。
传入连接指示（连接请求）的最大队列长度设置为`50` 。 如果队列已满时连接指示到达，则拒绝连接。

## 成员方法

`public Socket accept()`
侦听对此套接字的连接并接受它。

## 实现步骤

1. 创建服务器套接字对象和系统要指定的端口号

2. 使用accept()方法，获取到请求的客户端对象Socket

3. 使用流对象...

```java
package com.ntework.demo1;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Description 服务器端，接收客户端发来的连接请求,给客户端返回数据
 * @Classname Server
 * @Date 2021/8/18 10:44
 * @Created by 折腾的小飞
 */
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(2000);
        Socket socket = ss.accept();
        System.out.println("获得客户端的连接，监听端口"+socket.getLocalPort());

        InputStream is = socket.getInputStream();
        byte[] bytes=new byte[1024];
        int len=is.read(bytes);
        System.out.println(new String(bytes, 0, len));

        OutputStream os = socket.getOutputStream();
        os.write("我已接收到了你的信息，感谢！".getBytes());
        socket.close();
        ss.close();
    }
}

```

# 文件的上传和下载

## `shutdownOutput`

`void shutdownOutput()：禁用文件的输出流`
*​*

## 客户端上传

![image-20211124225515458](https://note-1259190304.cos.ap-chengdu.myqcloud.com/note/image-20211124225515458.png)

```java
package com.network.demo2;

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

/**
 * @Description 上传客户端
 * @Classname UpLoadClient
 * @Date 2021/8/18 13:44
 * @Created by 折腾的小飞
 */
public class UploadClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 3000);

        OutputStream os = socket.getOutputStream();
        FileInputStream fis = new FileInputStream(new File("C:\\Users\\折腾的小飞\\Desktop\\图片\\code\\java.png"));
        int len;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }
        //结束标识
//        void shutdownOutput()：禁用文件的输出流
        socket.shutdownOutput();

        InputStream is = socket.getInputStream();
        while ((len = is.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, len));
        }
        socket.close();
    }
}

```

## 服务端下载

![image-20211124225527319](https://note-1259190304.cos.ap-chengdu.myqcloud.com/note/image-20211124225527319.png)

```java
package com.network.demo2;

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

/**
 * @Description 上传服务端
 * @Classname UploadServer
 * @Date 2021/8/18 13:44
 * @Created by 折腾的小飞
 */
public class UploadServer {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(3000);
        Socket socket=ss.accept();

        FileOutputStream fos=new FileOutputStream(new File("java.png"));
        InputStream is=socket.getInputStream();
        int len;
        byte[] bytes=new byte[1024];
        while ((len=is.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }
        socket.shutdownInput();

        OutputStream os=socket.getOutputStream();
        os.write("已接收文件!".getBytes());
        ss.close();
        socket.close();
    }
}

```

## Client，Server

```java
package com.network.Work8_18;

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

/**
 * @Description 服务器，接收客户端的信息，并存储文件或者发送要下载图片的信息
 * @Classname Server
 * @Date 2021/8/18 20:31
 * @Created by 折腾的小飞
 */
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(6000);
        System.out.println("等待连接。。。");
        Socket socket = ss.accept();
        System.out.println("开始监听端口：" + ss.getLocalPort());

        // 创建文件，接收来自客户端的信息，存储到磁盘文件中
        InputStream is = socket.getInputStream();
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("img\\java.png"));
        int len;
        byte[] bytes = new byte[1024];
        while ((len = is.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
            bos.flush();
        }
        System.out.println("完成接收客户端的信息，存储完成！");
        bos.close();

        // 读取磁盘文件，向客户端发送
        OutputStream os = socket.getOutputStream();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("img\\java.png"));
        while ((len = bis.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }
        // 发送完成信号
        socket.shutdownInput();
        System.out.println("返回客户端的请求下载图片的请求，发送完成！");
        bis.close();

        socket.close();
    }
}

package com.network.Work8_18;

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

/**
 * @Description 客户端，像服务器发送下载图片请求，接收来自服务器端的图片信息
 * @Classname Client
 * @Date 2021/8/18 20:31
 * @Created by 折腾的小飞
 */
public class Client {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 6000);
            // 新建目录
            File file=new File("img");
            if (!file.exists()){
                file.mkdir();
            }
            // 读取磁盘文件，向服务器发送
            FileInputStream fis = new FileInputStream("java.png");
            OutputStream os = socket.getOutputStream();
            int len;
            byte[] bytes = new byte[1024];
            while ((len = fis.read(bytes)) != -1) {
                os.write(bytes, 0, len);
            }
            // 发送传输完成信息
            socket.shutdownOutput();
            System.out.println("向服务器-传输完成！");
            fis.close();

            // 创建磁盘文件，接收来自服务器端的信息，存储到文件中
            FileOutputStream fos=new FileOutputStream("java2.png");
            InputStream is=socket.getInputStream();
            while ((len=is.read(bytes))!=-1){
                fos.write(bytes,0,len);
                fos.flush();
            }
            System.out.println("从服务器-接收完成！");
            fos.close();

            socket.close();

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


    }
}
```

![image-20211124225541600](https://note-1259190304.cos.ap-chengdu.myqcloud.com/note/image-20211124225541600.png)

# 单人聊天

## `OutputStreamWriter`

`public class OutputStreamWriter extends Writer`

OutputStreamWriter是从**字符流** 到**字节流** 的桥接器：使用指定的`charset`写入其中的字符编码为字节。

## 构造方法

`public OutputStreamWriter(OutputStream out, Charset cs)`
创建使用给定charset的OutputStreamWriter。

## Server

```java
package com.network.demo4;

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

/**
 * @Description TODO
 * @Classname Server
 * @Date 2021/8/18 17:43
 * @Created by 折腾的小飞
 */
public class Server {
    private ServerSocket serverSocket;

    public static void main(String[] args) {
        try {
            Server server=new Server();
            server.work();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Server() throws IOException {
        System.out.println("服务器初始化");
        this.serverSocket=new ServerSocket(5000);
        System.out.println("服务器初始化完成，等待客户端连接...");
    }

    public void work(){
        try {
            Socket socket=serverSocket.accept();
            System.out.println("已接收到一个客户端连接");

            ClientHandler clientHandler=new ClientHandler(socket);
            Thread thread=new Thread(clientHandler);
            thread.start();

            InputStream is=socket.getInputStream();
            InputStreamReader isr=new InputStreamReader(is,"UTF-8");
            BufferedReader br=new BufferedReader(isr);
            while (true){
                String line = br.readLine();
                System.out.println("客户端："+line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private class ClientHandler implements Runnable{
        private Socket socket;

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

        @Override
        public void run() {
            try {
                OutputStream os=socket.getOutputStream();
                OutputStreamWriter osw=new OutputStreamWriter(os,"UTF-8");
                PrintWriter pw=new PrintWriter(osw,true);
                Scanner sc=new Scanner(System.in);
                while (true){
                    String line = sc.nextLine();
                    pw.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
```

## Client

```java
package com.network.demo4;

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

/**
 * @Description TODO
 * @Classname Client
 * @Date 2021/8/18 17:43
 * @Created by 折腾的小飞
 */
public class Client {
    private Socket socket;

    public static void main(String[] args) {
        try {
            Client client=new Client();
            client.work();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Client() throws IOException {
        System.out.println("开始建立连接");
        this.socket=new Socket("localhost",5000);
        System.out.println("连接已建立");
    }

    public void work(){
        try {

            ServerHandle serverHandle=new ServerHandle();
            Thread thread=new Thread(serverHandle);
            thread.start();

            OutputStream os=socket.getOutputStream();
            OutputStreamWriter osw=new OutputStreamWriter(os,"UTF-8");
            PrintWriter pw=new PrintWriter(osw,true);
            Scanner sc=new Scanner(System.in);
            while (true){
                String line = sc.nextLine();
                pw.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private class ServerHandle implements Runnable{

        @Override
        public void run() {
            try {
                InputStream is=socket.getInputStream();
                InputStreamReader isr=new InputStreamReader(is,"UTF-8");
                BufferedReader br=new BufferedReader(isr);
                String msg;
                while ((msg=br.readLine())!=null){
                    System.out.println("服务器："+msg);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

```

![image-20211124225556820](https://note-1259190304.cos.ap-chengdu.myqcloud.com/note/image-20211124225556820.png)
