JavaSE---网络编程

本篇博客继上一篇内容继续记录听黑马课的时候的笔记以及课堂上练习的代码,文章图源于我在听课的时候所截的屏,所以有些不清晰,请见谅。下面是课程链接,可点击自行跳转。

【黑马程序员Java零基础视频教程_下部(Java入门,含斯坦福大学练习题+力扣算法题和大厂java面试题)】 https://www.bilibili.com/video/BV1yW4y1Y7Ms/?share_source=copy_web&vd_source=d521b664e1113402904fa9336bd1d0ac


目录

初识

网络编程三要素

IP

IPV4和IPV6

IPV4小细节

InetAddress类的使用

端口号

协议

UDP协议

发送数据

接收数据

聊天室

单播、组播、广播

TCP协议

发送和接收数据

代码细节

三次握手和四次挥手

综合练习

多发多收

接收和反馈

上传文件

文件名重复问题

上传文件(多线程版)

上传文件(线程池优化)

BS(接收浏览器的消息并打印)


初识

网络编程三要素

IP

IPV4和IPV6

IPV4小细节

InetAddress类的使用

|-------------------------------------------|----------------------------------|
| static InetAddress getByName(String host) | 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 |
| String getHostName() | 获取此IP地址的主机名 |
| String getHostAddress() | 返回文本显示中的IP地址字符串 |

获取到IP地址相当于获取到了一个电脑,因为一个IP地址是网络上唯一标识主机,所以就能对获得的电脑做后续操作。

小练手(获取ip信息):

java 复制代码
package Internet.MyInetAddress;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class demo1 {
    public static void main(String[] args) throws UnknownHostException {
        /*
                static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
                String getHostName()                         获取此IP地址的主机名
                String getHostAddress()                      返回文本显示中的IP地址字符串
        */
        InetAddress address = InetAddress.getByName("LAPTOP-VUFPBHN3");
        System.out.println(address);

        String name = address.getHostName();
        System.out.println(name);

        String ip = address.getHostAddress();
        System.out.println(ip);
    }
}

端口号

两台电脑(电脑A和电脑B)之间发送消息时,端口起到关键作用。端口可理解为电脑收发数据的出入口,有编号且范围是0到65535。软件启动后必须绑定端口,否则程序只能单机运行,无法对外收发数据。比如微信启动时绑定65533端口,电脑A的微信通过65533端口发消息,电脑B的微信也绑定了65533端口,所以消息能被电脑B的微信接收,这就是端口号的作用。

协议

重要,需背

UDP协议

发送数据

小练手(UDP实现):

java 复制代码
package Internet.SendMessage;

import java.io.IOException;
import java.net.*;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        //发送数据

        //1.创建DatagramSocket对象(快递公司)
        //细节:
        //绑定端口,以后我们就是通过这个端口往外发送
        //空参:所有可用的端口中随机一个进行使用
        //有参:指定端口号进行绑定
        DatagramSocket socket = new DatagramSocket();
        //2.打包数据
        String str = "hello";
        byte[] buf = str.getBytes();
        InetAddress address = InetAddress.getByName("127.0.0.1");
        DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 1864);
        //3.发送数据
        socket.send(packet);
        //4.释放资源
        socket.close();
    }
}
接收数据

小练手(接收数据):

java 复制代码
package Internet.SendMessage;

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

public class ReceiveMessageDemo {
    public static void main(String[] args) throws IOException {
        //接收数据
        //1.创建DatagramSocket对象(快递公司)
        //细节:
        //接收时需要绑定端口
        //绑定的端口要和发送方一致
        DatagramSocket ad = new DatagramSocket(1864);
        //接收数据包
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf, buf.length);
        ad.receive(dp);
        //解析数据包
        byte[] data = dp.getData();
        int len = dp.getLength();
        InetAddress address = dp.getAddress();
        int port = dp.getPort();
        System.out.println("接收到数据"+new String(data,0,len));
        System.out.println("数据是从"+address+"这台电脑中的"+port+"这个端口发出的");
    }
}

在运行时,需要先运行接收方的端口,再运行发送方的端口。

receive该方法是阻塞的,程序执行到这一步的时候,会在这里死等,等发送端发送消息

System.out.println(11111);

ds.receive(dp);

System.out.println(2222);

聊天室

小练手(实现聊天室效果):

java 复制代码
//receiveTest1.java
package Internet.udpMessage2;

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

public class receiveTest1 {
    public static void main(String[] args) throws IOException {
        //创建快递公司
        DatagramSocket socket = new DatagramSocket(1234);
        //创建数据包
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        while (true) {
            socket.receive(dp);
            //解析数据包信息
            //创建一个新的包来接收解析的数据
            byte[] data = dp.getData();
            int len = dp.getLength();
            //获取主机地址真正的IP地址以及主机名称
            String hostAddress = dp.getAddress().getHostAddress();
            String name = dp.getAddress().getHostName();
            int port = dp.getPort();
            //读取数据长度为len的数据
            String str = new String(data,0,len);

            System.out.println("来自"+hostAddress+"主机名为:"+name+"端口号为:"+port+"发送来的数据:");
            System.out.println(str);
        }

    }
}
//sendTest1.java
package Internet.udpMessage2;

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

public class sendTest1 {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        //创建发送字符串
        Scanner sc = new Scanner(System.in);
        while (true) {
            String str = sc.nextLine();
            if (str.equals("886")){
                break;
            }
            byte[] buf = str.getBytes();
            InetAddress address = InetAddress.getByName("127.0.0.1");
            int port = 1234;
            //打包
            DatagramPacket dp = new DatagramPacket(buf,buf.length,address,port);
            //发送数据
            socket.send(dp);
        }
        socket.close();
    }
}

在编辑配置这个地方勾选上这个选项,就能实现一个程序运行多次,从而实现聊天室效果。一个发送程序就可看作一个人,可以在接收端看到所有人的发送信息。

单播、组播、广播

小练手(组播实现):

java 复制代码
//sendTest1.java
package Internet.udpMessage3;

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

public class sendTest1 {
    public static void main(String[] args) throws IOException {
        //实现组播
        //创建对象
        MulticastSocket ms = new MulticastSocket();
        //传输的话语
        String str = "love youself and love what you love";
        //创建字节数组
        byte[] buf = str.getBytes();
        //获取目的IP地址
        InetAddress address = InetAddress.getByName("230.0.0.1");
        //打成数据包
        DatagramPacket dp  = new DatagramPacket(buf,buf.length,address,1234);
        //发送
        ms.send(dp);
        //释放资源
        ms.close();
    }
}
//receiveTest1.java
package Internet.udpMessage3;

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

public class receiveTest1 {
    public static void main(String[] args) throws IOException {
        //创建对象
        MulticastSocket socket = new MulticastSocket(1234);
        //将当前的IP地址划入组网地址中
        //获取224.0.0.1的IP地址
        InetAddress address = InetAddress.getByName("230.0.0.1");
        //添加进去
        socket.joinGroup(address);
        //获取数据包
        //创建接收时的字节数组
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        socket.receive(dp);
        //解析数据包
        //创建数组接收数据
        byte[] data = dp.getData();
        int len = dp.getLength();
        String hostAddress = dp.getAddress().getHostAddress();
        String hostName = InetAddress.getLocalHost().getHostName();
        System.out.println("IP为:"+hostAddress+"主机名为:"+hostName+"电脑发送过来的信息:");
        System.out.println(new String(data,0,len));
    }
}
//receiveTest2.java
package Internet.udpMessage3;

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

public class receiveTest2 {
    public static void main(String[] args) throws IOException {
        //创建对象
        MulticastSocket socket = new MulticastSocket(1234);
        //将当前的IP地址划入组网地址中
        //获取224.0.0.1的IP地址
        InetAddress address = InetAddress.getByName("230.0.0.1");
        //添加进去
        socket.joinGroup(address);
        //获取数据包
        //创建接收时的字节数组
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        socket.receive(dp);
        //解析数据包
        //创建数组接收数据
        byte[] data = dp.getData();
        int len = dp.getLength();
        String hostAddress = dp.getAddress().getHostAddress();
        String hostName = InetAddress.getLocalHost().getHostName();
        System.out.println("IP为:"+hostAddress+"主机名为:"+hostName+"电脑发送过来的信息:");
        System.out.println(new String(data,0,len));
    }
}
//receiveTest3.java
package Internet.udpMessage3;

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

public class receiveTest3 {
    public static void main(String[] args) throws IOException {
        //创建对象
        MulticastSocket socket = new MulticastSocket(1234);
        //将当前的IP地址划入组网地址中
        //获取224.0.0.1的IP地址
        InetAddress address = InetAddress.getByName("230.0.0.1");
        //添加进去
        socket.joinGroup(address);
        //获取数据包
        //创建接收时的字节数组
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        socket.receive(dp);
        //解析数据包
        //创建数组接收数据
        byte[] data = dp.getData();
        int len = dp.getLength();
        String hostAddress = dp.getAddress().getHostAddress();
        String hostName = InetAddress.getLocalHost().getHostName();
        System.out.println("IP为:"+hostAddress+"主机名为:"+hostName+"电脑发送过来的信息:");
        System.out.println(new String(data,0,len));
    }
}

广播的话,就直接将地址修改为255.255.255.255即可实现

TCP协议

发送和接收数据

小练手(TCP通信客户端服务器端实现):

java 复制代码
//client.java
package Internet.tcpdemo1;

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

public class client {
    public static void main(String[] args) throws IOException {
        //客户端  输出流
        //创建客户端的Socket对象与指定服务端连接
        Socket socket = new Socket("127.0.0.1", 1234);
        //获取输出流
        OutputStream outputStream = socket.getOutputStream();
        //写数据
        outputStream.write("love youself and love what you love".getBytes());
        //释放资源
        socket.close();
    }
}
//serever.java
package Internet.tcpdemo1;

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

public class serever {
    public static void main(String[] args) throws IOException {
        //服务器 输入流
        //创建服务器端的Socket对象
        ServerSocket serverSocket = new ServerSocket(1234);
        //监听客户端连接,返回Socket对象
        Socket socket = serverSocket.accept();
        //获取输入流
        InputStream is = socket.getInputStream();
        //创建字节数组
        byte[] buf = new byte[1024];
        int len;
        while ((len=is.read(buf)) != -1){
            System.out.println(new String(buf,0,len));
        }
        //释放资源
        is.close();
        serverSocket.close();
    }
}

注意:上述代码中传输中文可能会出现乱码,所以最稳妥的方法是服务器端读取数据时,用InputStreamReader方法将字节流转化为字符流。

小练手(确保中文可以正常读取并提高读取效率):

java 复制代码
//serever.java
package Internet.tcpdemo1;

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

public class serever {
    public static void main(String[] args) throws IOException {
        //服务器 输入流
        //创建服务器端的Socket对象
        ServerSocket serverSocket = new ServerSocket(1234);
        //监听客户端连接,返回Socket对象
        Socket socket = serverSocket.accept();
        //获取输入流
        InputStream is = socket.getInputStream();
        //转换成字符流
        InputStreamReader isr = new InputStreamReader(is);
        //提高效率的话可以进一步转换为缓冲流
        BufferedReader br = new BufferedReader(isr);
        int c;
        while ((c=br.read())!=-1){
            System.out.print((char)c);
        }
        //        //创建字节数组
//        byte[] buf = new byte[1024];
//        int len;
//        while ((len=is.read(buf)) != -1){
//            System.out.println(new String(buf,0,len));
//        }
        //释放资源
        is.close();
        serverSocket.close();
    }
}
//client.java
package Internet.tcpdemo1;

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

public class client {
    public static void main(String[] args) throws IOException {
        //客户端  输出流
        //创建客户端的Socket对象与指定服务端连接
        Socket socket = new Socket("127.0.0.1", 1234);
        //获取输出流
        OutputStream outputStream = socket.getOutputStream();
        //写数据
        //outputStream.write("love youself and love what you love".getBytes());
        outputStream.write("你好你好".getBytes());
        //释放资源
        socket.close();
    }
}
代码细节

TCP 通信流程及重要点整理

运行顺序

在 TCP 通信中,需先运行服务端 ,再运行客户端。若先运行客户端,由于服务端未启动,客户端在尝试与服务端(127.0.0.110000 端口)建立连接时,因无服务端响应,第一行代码就会报错。

服务端流程

  1. 绑定端口 :通过 ServerSocket ss = new ServerSocket(10000);10000 端口绑定,为接收客户端连接做准备。
  2. 等待客户端连接 :执行 Socket socket = ss.accept();,该方法会阻塞,直到有客户端发起连接。当客户端连接后,返回客户端的连接对象 socket

客户端流程

  1. 建立连接 :通过 Socket socket = new Socket("127.0.0.1", 10000); 与服务端(127.0.0.110000 端口)建立连接,底层通过三次握手协议保证连接可靠建立,若连接失败会报错。
  2. 发送数据 :从连接通道获取输出流 OutputStream os = socket.getOutputStream();,然后通过 os.write("aaa".getBytes()); 写出数据(示例中发送"aaa")。

数据传输

  • 客户端通过输出流往连接通道写数据,服务端通过输入流从连接通道读数据,均以 IO 流形式操作,且 IO 流是从连接通道中获取的,并非自行创建。

资源释放

  1. 服务端 :需释放 socket(客户端连接对象)和 ssServerSocket 对象),即 socket.close();ss.close();
  2. 客户端 :需释放 os(输出流,可关可不关,关闭连接通道时会自动处理)和 socket,即 os.close();(可选)和 socket.close();
    在关闭连接(如执行 socket.close())时,底层通过四次挥手协议,确保连接通道内的数据已被处理完毕,避免数据丢失。
三次握手和四次挥手

综合练习

多发多收

小练手(多发多收):

java 复制代码
//Client.java
package Internet.Test1;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        //客户端 输出流
        Socket socket = new Socket("127.0.0.1",1234);
        //创建输出流
        OutputStream os = socket.getOutputStream();
        //手动输入发送的信息
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入要发送的数据:");
            String str = sc.nextLine();
            //进行写入,并判断是否结束
            if (str.equals("886")){
                break;
            }
            os.write(str.getBytes());
        }
        //释放资源
        os.close();
        socket.close();
    }
}
//Server.java
package Internet.Test1;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //服务器端  输入流 input
        ServerSocket sc = new ServerSocket(1234);
        //获取Socket对象
        Socket socket = sc.accept();
        //获取输入流
        InputStream is = socket.getInputStream();
        //读取数据
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        int ch;
        while ((ch = br.read())!= -1){
            System.out.print((char)ch);
        }
        //释放资源
        socket.close();
        sc.close();
    }
}

接收和反馈

细节:

read方法会从连接通道中读取数据

但是,需要有一个结束标记,此处的循环才会停止

否则,程序就会一直停在read方法这里,等待读取下面的数据

小练手(接收和反馈):

java 复制代码
//Client.java
package Internet.Test2;

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

public class Client {
    public static void main(String[] args) throws IOException {
        //客户端 写出数据
        //创建Socket对象
        Socket socket = new Socket("127.0.0.1",1234);
        //获取输出流
        OutputStream os = socket.getOutputStream();
        //向其中写数据
        os.write("见到你很高兴".getBytes());

        //停止输出流,结束标识符,从而确保Server的循环读取可以跳出
        socket.shutdownOutput();
        //收到服务器的回复
        InputStream is = socket.getInputStream();
        //转换成字符流
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        int ch;
        while((ch = br.read()) != -1){
            System.out.print((char)ch);
        }

        //释放资源
        socket.close();

    }
}
//Server.java
package Internet.Test2;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //服务器端 写入数据 input
        //创建对象
        ServerSocket ss = new ServerSocket(1234);
        //获取Socket对象
        Socket socket = ss.accept();
        //获取写入流对象
        InputStream is = socket.getInputStream();
        //转换成字符流
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        int ch;
        while((ch = br.read()) != -1){
            System.out.print((char)ch);
        }
        //接收到客户端的信息之后回写数据
        String str = "谢谢";
        OutputStream os = socket.getOutputStream();
        os.write(str.getBytes());

        //释放资源
        socket.close();
        ss.close();

    }
}

上传文件

小练手(上传文件):

java 复制代码
//Client.java
package Internet.Test3;

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

public class Client {
    public static void main(String[] args) throws IOException {
        //客户端 写出数据 output
        Socket socket = new Socket("127.0.0.1",1234);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/a.txt"));
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = bis.read())!= -1){
            //利用循环将每次读取到的字节数组文件写出到写出流中
            bos.write(buf,0,len);
        }
        //往服务器写结束标识
        socket.shutdownOutput();
        //接收服务器的回复信息数据
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = br.readLine();
        System.out.println(line);

        //释放资源
        socket.close();
    }
}
//Server.java
package Internet.Test3;

import com.sun.xml.internal.ws.api.message.MessageWritable;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //服务器端 写入数据 input
        ServerSocket ss = new ServerSocket(1234);
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/b.txt"));
        int len;
        byte[] buf = new byte[1024];
        while ((len = bis.read(buf)) != -1){
            bos.write(buf,0,len);
        }
        //回写数据
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        bw.write("上传成功");
        bw.newLine();
        bw.flush();
        //释放资源
        socket.close();
        ss.close();
    }
}

文件名重复问题

小练手(UUID 随机生成名称):

java 复制代码
package Internet.Test4;

import java.io.IOException;
import java.util.UUID;

public class UUIDTest {
    public static void main(String[] args) {
        String str = UUID.randomUUID().toString().replace("-", "");
        System.out.println(str);
    }
}

只需在服务器端增加这个UUID相关代码,就可实现我们想要的效果。

小练手(文件名重复):

java 复制代码
//Client.java
package Internet.Test4;

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

public class Client {
    public static void main(String[] args) throws IOException {
        //客户端 写出数据 output
        Socket socket = new Socket("127.0.0.1",1234);

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/a.txt"));
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = bis.read())!= -1){
            //利用循环将每次读取到的字节数组文件写出到写出流中
            bos.write(buf,0,len);
        }
        //往服务器写结束标识
        socket.shutdownOutput();
        //接收服务器的回复信息数据
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = br.readLine();
        System.out.println(line);

        //释放资源
        socket.close();
    }
}
//Server.java
package Internet.Test4;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //服务器端 写入数据 input
        ServerSocket ss = new ServerSocket(1234);
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);

        //随机生成名称
        String name = UUID.randomUUID().toString().replace("-", "");
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/"+name+".txt"));

        int len;
        byte[] buf = new byte[1024];
        while ((len = bis.read(buf)) != -1){
            bos.write(buf,0,len);
        }
        //回写数据
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        bw.write("上传成功");
        bw.newLine();
        bw.flush();
        //释放资源
        socket.close();
        ss.close();
    }
}

上传文件(多线程版)

小练手(上传文件(多线程实现)):

java 复制代码
//myRunnable.java
package Internet.Test5;

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

public class myRunnable implements Runnable{

    Socket socket;

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

    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);

            //随机生成名称
            String name = UUID.randomUUID().toString().replace("-", "");
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/"+name+".txt"));

            int len;
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1){
                bos.write(buf,0,len);
            }
            //回写数据
            OutputStream os = socket.getOutputStream();
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
            bw.write("上传成功");
            bw.newLine();
            bw.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (socket != null) {
                //释放资源
                try {
                    socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }
}
//Server.java
package Internet.Test5;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //服务器端 写入数据 input
        ServerSocket ss = new ServerSocket(1234);
        while (true) {
            Socket socket = ss.accept();
            //开启一个线程
            //一个线程就为一个用户服务
            new Thread(new myRunnable(socket)).start();
        }

    }
}
//Client.java
package Internet.Test5;

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

public class Client {
    public static void main(String[] args) throws IOException {
        //客户端 写出数据 output
        Socket socket = new Socket("127.0.0.1",1234);

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/a.txt"));
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = bis.read())!= -1){
            //利用循环将每次读取到的字节数组文件写出到写出流中
            bos.write(buf,0,len);
        }
        //往服务器写结束标识
        socket.shutdownOutput();
        //接收服务器的回复信息数据
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = br.readLine();
        System.out.println(line);

        //释放资源
        socket.close();
    }
}

上传文件(线程池优化)

小练手(线程池优化):

java 复制代码
//Client.java
package Internet.Test6;

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

public class Client {
    public static void main(String[] args) throws IOException {
        //客户端 写出数据 output
        Socket socket = new Socket("127.0.0.1",1234);

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/a.txt"));
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = bis.read())!= -1){
            //利用循环将每次读取到的字节数组文件写出到写出流中
            bos.write(buf,0,len);
        }
        //往服务器写结束标识
        socket.shutdownOutput();
        //接收服务器的回复信息数据
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = br.readLine();
        System.out.println(line);

        //释放资源
        socket.close();
    }
}
//Server.java
package Internet.Test6;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Server {
    public static void main(String[] args) throws IOException {


        //创建线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                3,
                6,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        //服务器端 写入数据 input
        ServerSocket ss = new ServerSocket(1234);
        while (true) {
            Socket socket = ss.accept();
            //开启一个线程
            //一个线程就为一个用户服务
            //new Thread(new myRunnable(socket)).start();
            pool.submit(new myRunnable(socket));
        }

    }
}
//myRunnable.java
package Internet.Test6;

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

public class myRunnable implements Runnable{

    Socket socket;

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

    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);

            //随机生成名称
            String name = UUID.randomUUID().toString().replace("-", "");
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/"+name+".txt"));

            int len;
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1){
                bos.write(buf,0,len);
            }
            //回写数据
            OutputStream os = socket.getOutputStream();
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
            bw.write("上传成功");
            bw.newLine();
            bw.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (socket != null) {
                //释放资源
                try {
                    socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

        }
    }
}

BS(接收浏览器的消息并打印)

直接在浏览其中输入IP:端口号,按回车即可接收到浏览器信息。

小练手(BS接收浏览器的信息并打印):

java 复制代码
package Internet.test7;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //服务器 输入流
        //创建服务器端的Socket对象
        ServerSocket serverSocket = new ServerSocket(1234);
        //监听客户端连接,返回Socket对象
        Socket socket = serverSocket.accept();
        //获取输入流
        InputStream is = socket.getInputStream();
        //转换成字符流
        InputStreamReader isr = new InputStreamReader(is);
        //提高效率的话可以进一步转换为缓冲流
        BufferedReader br = new BufferedReader(isr);
        int c;
        while ((c=br.read())!=-1){
            System.out.print((char)c);
        }
        //        //创建字节数组
//        byte[] buf = new byte[1024];
//        int len;
//        while ((len=is.read(buf)) != -1){
//            System.out.println(new String(buf,0,len));
//        }
        //释放资源
        is.close();
        serverSocket.close();
    }
}

这篇文章就先更到这里,接下来的内容可查看我的下一篇博客,感谢观看,希望对你有帮助。

相关推荐
湖边看客2 小时前
antd x6 + vue3
开发语言·javascript·vue.js
赖small强2 小时前
【Linux 网络基础】libwebsockets HTTPS 服务端实现机制详解
linux·网络·https·tls·libwebsockets
带刺的坐椅2 小时前
Solon AI 开发学习5 - chat - 支持哪些模型?及方言定制
java·ai·openai·solon
小离a_a2 小时前
flex垂直布局,容器间距相等
开发语言·javascript·ecmascript
悟空码字2 小时前
单点登录:一次登录,全网通行
java·后端
傻啦嘿哟2 小时前
物流爬虫实战:某丰快递信息实时追踪技术全解析
java·开发语言·数据库
倚肆2 小时前
Spring Boot Security 全面详解与实战指南
java·spring boot·后端
码力码力我爱你3 小时前
Harmony OS C++实战
开发语言·c++
大白的编程日记.3 小时前
【计算网络学习笔记】MySql的多版本控制MVCC和Read View
网络·笔记·学习·mysql