网络通信,UDP通信,TCP通信

网络通信3要素

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

要素1:IP地址

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

IP地址操作类: InetAddress

在这里插入图片描述

package com.heima.test;

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

public class InetAddressDemo {
    public static void main(String[] args) throws Exception {
        //获取本机地址对象
        InetAddress ip1 = InetAddress.getLocalHost();
        //本机局域网ip地址
        System.out.println(ip1);
        //主机名
        System.out.println(ip1.getHostName());
        //局域网ip地址
        System.out.println(ip1.getHostAddress());

        //获取域名ip对象
        InetAddress ip2 = InetAddress.getByName("www.baidu.com");
        System.out.println(ip2.getHostName());
        System.out.println(ip2.getHostAddress());

        //获取公网ip对象
        InetAddress ip3 = InetAddress.getByName("119.63.197.151");
        System.out.println(ip3.getHostName());
        System.out.println(ip3.getHostAddress());

        //判断是否能通:ping 5s之内测试是否可通
        System.out.println(ip3.isReachable(5000));

    }
}

在这里插入图片描述

要素2:端口号

在这里插入图片描述

要素3:协议

  • 连接和通信数据的规则被称为网络通信协议

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

UDP通信

基础知识

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

package com.heima.test.TCP;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//接收端
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        System.out.println("============服务端先启动=============");

        //创建接收端对象,注册端口号要与发送端一致
        DatagramSocket socket = new DatagramSocket(8888);

        //创建数据包对象接收数据
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        //等待接受数据
        socket.receive(packet);

        //取出数据
        //读取多少倒出多少
        int len = packet.getLength();
        String s = new String(buffer, 0, len);
        System.out.println("收到了 :" + s);

        //获取发送端的ip和端口
        String ip = packet.getSocketAddress().toString();
        System.out.println("对方的地址 :" + ip);

        int port = packet.getPort();
        System.out.println("对方端口 : " + port);

        socket.close();
    }
}

在这里插入图片描述

package com.heima.test.TCP;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

//发送端
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        System.out.println("=================客户端后启动===================");
        //创建发送端对象,自带默认端口
        DatagramSocket socket = new DatagramSocket(6666);

        //创建一个数据包对象封装数据
//        public DatagramPacket(byte buf[], int length,
//        InetAddress address, int port) {
//            this(buf, 0, length, address, port);
        //buf[] 封装要发送的数据
        //length 此字节数组的长度
        //服务端ip地址
        //服务端端口
        byte[] buffer = "我是一个中国人".getBytes();
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 8888);

        //发送数据
        socket.send(packet);

        //关闭管道
        socket.close();
    }
}

在这里插入图片描述

在这里插入图片描述

多发多收

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 如果需要同时开启多个客户端,idea需要设置一下

在这里插入图片描述

package com.heima.test.TCP;

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

//发送端 多发多收
public class ClientDemo1 {
    public static void main(String[] args) throws Exception {
        System.out.println("=================客户端1后启动===================");
        //创建发送端对象,自带默认端口
        DatagramSocket socket = new DatagramSocket();

        Scanner sc = new Scanner(System.in);

        while (true) {
            //按行收发消息
            System.out.println("请你说 : ");
            String msg = sc.nextLine();

            if ("exit".equals(msg)){
                System.out.println("离线成功");
                socket.close();
                break;
            }

            //创建一个数据包对象封装数据
            byte[] buffer = msg.getBytes();
            //DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 8888);

            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("192.168.0.109"), 9999);

            //发送数据
            socket.send(packet);
        }

    }
}

package com.heima.test.TCP;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

//接收端
public class ServerDemo1 {
    public static void main(String[] args) throws Exception {
        System.out.println("============服务端1先启动=============");

        //创建接收端对象,注册端口号要与发送端一致
        DatagramSocket socket = new DatagramSocket(9999);

        //创建数据包对象接收数据
        byte[] buffer = new byte[1024 * 64];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            //等待接受数据
            socket.receive(packet);

            //取出数据
            //读取多少倒出多少
            int len = packet.getLength();
            String s = new String(buffer, 0, len);
            System.out.println("收到了来自 :" + packet.getAddress() + ",对方端口是" + packet.getPort() + "的消息 : " + s);

        }
    }
}

在这里插入图片描述
在这里插入图片描述

广播,组播

在这里插入图片描述
在这里插入图片描述

  • 广播
    package com.hyway.delivergoods.test;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.util.Scanner;
    
    public class UDPClientBroadcast {
        public static void main(String[] args) throws Exception {
            System.out.println("=========windows笔记本客户端启动=========");
    
            DatagramSocket socket = new DatagramSocket();
    
            Scanner sc = new Scanner(System.in);
    
            while (true) {
                System.out.println("请输入消息 : ");
    
                String msg = sc.nextLine();
    
                if ("exit".equals(msg)) {
                    System.out.println("离线成功");
                    socket.close();
                    return;
                }
    
                byte[] buffer = msg.getBytes();
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("255.255.255.255"), 9999);
    
                socket.send(packet);
            }
        }
    }

package com.hyway.delivergoods.test;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPServerBroadcast {
    public static void main(String[] args) throws Exception {
        System.out.println("=============windows笔记本服务端启动==============");

        DatagramSocket socket = new DatagramSocket(9999);

        byte[] buffer = new byte[1024 * 8];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            socket.receive(packet);

            int len = packet.getLength();
            String s = new String(buffer, 0, len);
            System.out.println("收到了来自mac :" + packet.getAddress() + ",对方端口是 " + packet.getPort() + "的消息 :" + s);
        }
    }
}

在这里插入图片描述
在这里插入图片描述

  • 组播
    在这里插入图片描述
package com.hyway.delivergoods.test;

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

public class UDPClientGroupcast {
    public static void main(String[] args) throws Exception {
        System.out.println("=========windows笔记本客户端启动=========");

        DatagramSocket socket = new DatagramSocket();

        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.println("请输入消息 : ");

            String msg = sc.nextLine();

            if ("exit".equals(msg)) {
                System.out.println("离线成功");
                socket.close();
                return;
            }

            byte[] buffer = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("224.0.1.1"), 9999);

            socket.send(packet);
        }
    }
}

package com.hyway.delivergoods.test;

import java.net.*;

public class UDPServerGroupcast {
    public static void main(String[] args) throws Exception {
        System.out.println("=============windows笔记本服务端启动==============");

        MulticastSocket socket = new MulticastSocket(9999);

        //当前接收端加入一个组播组中去,绑定对应的组播消息的组播IP
        //此方法可用,可是过时了
        //socket.joinGroup(InetAddress.getByName("224.0.1.1"));
        //第二个参数是当前主机所在的网段
        socket.joinGroup(new InetSocketAddress(InetAddress.getByName("224.0.1.1"),9999),
                NetworkInterface.getByInetAddress(InetAddress.getLocalHost()));

        byte[] buffer = new byte[1024 * 8];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            socket.receive(packet);

            int len = packet.getLength();
            String s = new String(buffer, 0, len);
            System.out.println("收到了来自mac :" + packet.getAddress() + ",对方端口是 " + packet.getPort() + "的消息 :" + s);
        }
    }
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

TCP通信

基础知识-Socket套接字

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.heima.test.TCP1;

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

//Socket网络编程的客户端,实现一发一收
public class SocketClient {
    public static void main(String[] args) {

        try {
            System.out.println("==============客户端启动成功==============");

            //创建Socket通信管道请求服务端的连接
            //服务端的IP地址,服务端的端口
            Socket socket = new Socket("127.0.0.1", 7777);

            //从socket通信管道中得到一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            //发送消息
            //因为服务端只能接收一行消息,会导致服务器端挂掉,Connection reset
            //ps.print("我是TCP客户端,我已经与你对接,并发出邀请:约吗?");
            ps.println("我是TCP客户端,我已经与你对接,并发出邀请:约吗?");
            ps.flush();

            //不要关闭资源,会导致有些信息发送丢失,除非用户点离线才关闭
            //socket.close();

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.heima.test.TCP1;

//Socket网络编程的服务端,实现接受消息

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 SocketServer {
    public static void main(String[] args) {

        try {
            System.out.println("==============服务端启动成功==============");
            //注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            //必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
            //进入等待状态
            Socket socket = serverSocket.accept();
            //从socket通信管道得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接收
            //BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息
            String msg;
            //while ((msg = br.readLine()) != null) {
            //while接收多行消息,服务器还是会死掉
            if ((msg = br.readLine()) != null) {
                System.out.println(socket.getRemoteSocketAddress() + "远程地址说了 : " + msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

多发多收消息

在这里插入图片描述

package com.heima.test.TCP1;

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

//Socket网络编程的客户端,实现多发多收
public class MultiSocketClient {
    public static void main(String[] args) {

        try {
            System.out.println("==============客户端启动成功==============");

            //创建Socket通信管道请求服务端的连接
            //服务端的IP地址,服务端的端口
            Socket socket = new Socket("127.0.0.1", 7777);

            //从socket通信管道中得到一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请说 : ");
                String msg = sc.nextLine();
                //发送消息
                ps.println(msg);
                ps.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

package com.heima.test.TCP1;

//Socket网络编程的服务端,实现接受消息

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 MultiSocketServer {
    public static void main(String[] args) {

        try {
            System.out.println("==============服务端启动成功==============");
            //注册端口
            ServerSocket serverSocket = new ServerSocket(7777);
            //必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
            //进入等待状态
            Socket socket = serverSocket.accept();
            //从socket通信管道得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接收
            //BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息
            String msg;
            while ((msg = br.readLine()) != null) {
                System.out.println(socket.getRemoteSocketAddress() + "远程地址说了 : " + msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

同时接受多个客户端消息(重点)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.heima.test.TCP1;

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

//Socket网络编程的客户端,实现服务端可以同时处理多个客户端消息
public class ThreadSocketClient {
    public static void main(String[] args) {

        try {
            System.out.println("==============客户端启动成功==============");

            //创建Socket通信管道请求服务端的连接
            //服务端的IP地址,服务端的端口
            Socket socket = new Socket("127.0.0.1", 7777);

            //从socket通信管道中得到一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请说 : ");
                String msg = sc.nextLine();
                //发送消息
                ps.println(msg);
                ps.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

package com.heima.test.TCP1;

//Socket网络编程的服务端,实现服务端可以同时处理多个客户端消息

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 ThreadSocketServer {
    public static void main(String[] args) {

        try {
            System.out.println("==============服务端启动成功==============");
            //注册端口
            ServerSocket serverSocket = new ServerSocket(7777);

            //定义一个死循环由主线程负责不断地接收客户端的Socket管道连接
            while (true) {
                //每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
                Socket socket = serverSocket.accept();

                System.out.println(socket.getRemoteSocketAddress()+" 上线了!");

                //创建独立线程处理socket
                new ServerReaderThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

package com.heima.test.TCP1;

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

public class ServerReaderThread extends Thread {
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从socket通信管道得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息
            String msg;
            while ((msg = br.readLine()) != null) {
                System.out.println(socket.getRemoteSocketAddress() + " 远程地址说了 : " + msg);
            }
        } catch (Exception e) {
           // e.printStackTrace();
            System.out.println(socket.getRemoteSocketAddress() + " 离开了!!!");
        }
    }
}

在这里插入图片描述

使用线程池优化

在这里插入图片描述
在这里插入图片描述

package com.heima.test.TCP1;

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

//Socket网络编程的客户端,实现服务端可以同时处理多个客户端消息

//使用线程池优化代码
//客户端不用动
public class ThreadSocketClient {
    public static void main(String[] args) {

        try {
            System.out.println("==============客户端启动成功==============");

            //创建Socket通信管道请求服务端的连接
            //服务端的IP地址,服务端的端口
            Socket socket = new Socket("127.0.0.1", 6666);

            //从socket通信管道中得到一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请说 : ");
                String msg = sc.nextLine();
                //发送消息
                ps.println(msg);
                ps.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

package com.heima.test.TCP1;

//Socket网络编程的服务端,实现服务端可以同时处理多个客户端消息
//使用线程池优化代码

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

public class ThreadSocketServer {
    //使用静态变量记住一个线程池对象,用于处理任务
    //上限是5线程或7任务
    private static ExecutorService pool = new ThreadPoolExecutor(3, 5, 6,
            TimeUnit.SECONDS, new ArrayBlockingQueue<>(2),
            Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {

        try {
            System.out.println("==============服务端启动成功==============");
            //注册端口
            ServerSocket serverSocket = new ServerSocket(6666);

            //定义一个死循环由主线程负责不断地接收客户端的Socket管道连接
            while (true) {
                //每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress() + " 上线了!");

                //创建任务对象交给线程池处理
                //任务对象负责读取消息
                Runnable target = new ServerReaderRunnable(socket);
                pool.execute(target);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

package com.heima.test.TCP1;

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

//任务队列
public class ServerReaderRunnable implements Runnable {
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从socket通信管道得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息
            String msg;
            while ((msg = br.readLine()) != null) {
                System.out.println(socket.getRemoteSocketAddress() + " 远程地址说了 : " + msg);
            }
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + " 离开了!!!");
        }
    }
}

在这里插入图片描述

实战案例 - 即时通信

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.heima.test.TCP2;

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

//客户端既能收消息,也可以发送消息
public class ClientMSG {
    public static void main(String[] args) {

        try {
            System.out.println("==============客户端启动成功==============");

            //创建Socket通信管道请求服务端的连接
            //服务端的IP地址,服务端的端口
            Socket socket = new Socket("127.0.0.1", 6666);

            //创建一个独立的线程专门负责这个客户端的读消息(服务端随时可能转发消息过来!)
            new ClientReaderThread(socket).start();

            //从socket通信管道中得到一个字节输出流,负责发送数据
            OutputStream os = socket.getOutputStream();

            //把低级的字节流包装成打印流
            PrintStream ps = new PrintStream(os);

            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请说 : ");
                String msg = sc.nextLine();
                //发送消息
                ps.println(msg);
                ps.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

//客户端读线程
class ClientReaderThread extends Thread {
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从socket通信管道得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息
            String msg;
            while ((msg = br.readLine()) != null) {
                System.out.println(" 收到了消息 : " + msg);
            }
        } catch (Exception e) {
            System.out.println("服务端把你踢出去了。。。");
        }
    }
}
package com.heima.test.TCP2;

import com.heima.test.TCP1.ServerReaderRunnable;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class ServerMSG {
    //定义一个静态的List集合存储当前全部在线socket管道
    public static List<Socket> allOnlineSocket = new ArrayList<>();

    public static void main(String[] args) {
        try {
            System.out.println("==============服务端启动成功==============");
            //注册端口
            ServerSocket serverSocket = new ServerSocket(6666);

            //循环接收客户端socket管道请求
            while (true) {
                //开始接收客户端的socket管道连接请求
                //注意:在这里等待客户端的socket管道连接
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress() + " 上线了!");

                allOnlineSocket.add(socket);//上线完成

                //创建一个独立的线程来单独处理这个socket管道
                new ServerReaderThread(socket).start();

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

class ServerReaderThread extends Thread {
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从socket通信管道得到一个字节输入流
            InputStream is = socket.getInputStream();
            //把字节输入流包装成缓冲字符输入流进行消息的接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            //按照行读取消息
            String msg;
            while ((msg = br.readLine()) != null) {
                System.out.println(socket.getRemoteSocketAddress() + " 发来了 : " + msg);
                //把这个消息进行端口转发给全部客户端socket管道
                sendMsgToAll(msg);
            }
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + " 离开了!!!");
            ServerMSG.allOnlineSocket.remove(socket);
        }
    }

    private void sendMsgToAll(String msg) throws Exception {
        for (Socket socket : ServerMSG.allOnlineSocket) {
            PrintStream ps = new PrintStream(socket.getOutputStream());
            ps.println(msg);
            ps.flush();
        }
    }
}

  • 没有排除自己,自己也能收到消息
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

实战案例 - 模拟BS系统

在这里插入图片描述

在这里插入图片描述

package com.heima.test.TCP3;

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

public class BSserver {
    public static void main(String[] args) {
        try {
            System.out.println("==============服务端启动成功==============");
            //注册端口
            ServerSocket ss = new ServerSocket(8080);
            //创建一个循环接收多个客户端请求
            while (true) {
                Socket socket = ss.accept();
                //交给一个独立线程处理
                new ServerReaderThread(socket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

class ServerReaderThread extends Thread {
    private Socket socket;
    public ServerReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            //浏览器已经与本线程建立了socket管道
            //响应消息给浏览器显示
            PrintStream ps = new PrintStream(socket.getOutputStream());
            //必须响应HTTP协议格式数据,否则浏览器·不认识消息
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Type:text/html;charset=UTF-8");
            ps.println();//必须发送一个空行
            //才可以响应数据回去给浏览器
            ps.println("<span style='color:red;font-size:90px'>我是响应信息</span>");
            ps.close();
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + " 离开了!!!");
        }
    }
}

在这里插入图片描述

  • 使用线程池实现
package com.heima.test.TCP3;

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

public class BSserver {
    //使用静态变量记住一个线程池对象,用于处理任务
    //上限是5线程或7任务
    private static ExecutorService pool = new ThreadPoolExecutor(3, 5, 6,
            TimeUnit.SECONDS, new ArrayBlockingQueue<>(2),
            Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        try {
            System.out.println("==============服务端启动成功==============");
            //注册端口
            ServerSocket ss = new ServerSocket(8080);
            //创建一个循环接收多个客户端请求
            while (true) {
                Socket socket = ss.accept();
                //交给一个独立线程处理
                pool.execute(new ServerReaderRunnable(socket));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

class ServerReaderRunnable implements Runnable {
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //浏览器已经与本线程建立了socket管道
            //响应消息给浏览器显示
            PrintStream ps = new PrintStream(socket.getOutputStream());
            //必须响应HTTP协议格式数据,否则浏览器·不认识消息
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Type:text/html;charset=UTF-8");
            ps.println();//必须发送一个空行
            //才可以响应数据回去给浏览器
            ps.println("<span style='color:red;font-size:90px'>我是响应信息2</span>");
            ps.close();
        } catch (Exception e) {
            System.out.println(socket.getRemoteSocketAddress() + " 离开了!!!");
        }
    }
}

在这里插入图片描述

在这里插入图片描述