day29-java

网络编程

网络通信基本模式

*CS模式:*客户端和服务端模式,客户端和服务端都由程序员开发,用户需要安装客户端

*BS模式:*用户通过浏览器访问服务端,服务端由程序员开发

网络通信三要素

IP地址

设备在网络中的地址,是唯一标识

常用ip命令:

查看本机IP地址:ipconfig

检查网络是否连通:ping IP地址

局域网网址

192.168. 开头的就是常见的局域网地址,范围即为192.168.0.0–192.168.255.255,专门为组织机构内部使用

特殊IP地址

本机IP: 127.0.0.1或者localhost:称为回送地址也可称本地回环地址,只会寻找当前所在本机。

IP地址操作类:InetAddress
package com.itheima.inetadress;

import java.net.InetAddress;

/**
 目标:InetAddress类概述(了解)
 一个该类的对象就代表一个IP地址对象。

 InetAddress类成员方法:
 static InetAddress getLocalHost()
 * 获得本地主机IP地址对象。
 static InetAddress getByName(String host)
 * 根据IP地址字符串或主机名获得对应的IP地址对象。
 String getHostName()
 * 获得主机名。
 String getHostAddress()
 * 获得IP地址字符串。
 */
public class Demo01 {
    public static void main(String[] args) throws Exception {
        //获取本地主机IP地址对象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);
        System.out.println(localHost.getHostAddress());
        System.out.println(localHost.getHostName());

        //根据IP地址字符串或主机名获得相应的IP地址对象
        InetAddress ip1 = InetAddress.getByName("www.baidu.com");
        System.out.println(ip1.getHostName());
        System.out.println(ip1.getHostAddress());
    }
}

端口号

应用程序在设备中的唯一标识,被规定为一个 16 位的二进制,范围是 0~65535。

端口类型

周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用 80,FTP占用21)
注册端口:1024~49151,分配给用户进程或某些应用程序。(如:Tomcat占 用8080,MySQL占用3306)
动态端口:49152到65535,之所以称为动态端口,是因为它 一般不固定分配某种进程,而是动态分配。

注意:我们自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。

协议

数据在网络中传输的规则,常见协议有:TCP,UDP

网络通信参考模型

OSI参考模型:世界互联协议标准,全球通信规范,由于此模型过于理想化,未能在因特网上进行广泛推广。
TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

传输层的两个常见协议

TCP(Transmission Control Protocol) :传输控制协议
UDP(User Datagram Protocol):用户数据报协议

TCP协议特点

使用TCP协议,必须双方先建立连接,它是一种面向连接的可靠通信协议。
传输前,采用“三次握手”方式建立连接,所以是可靠的 。
在连接中可进行大数据量的传输 。
连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低。

TCP协议通信场景

对信息安全要求较高的场景,例如:文件下载、金融等数据通信。

UDP协议特点

UDP是一种无连接、不可靠传输的协议。
将数据源IP、目的地IP和端口封装成数据包,不需要建立连接
每个数据包的大小限制在64KB内
发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
可以广播发送 ,发送数据结束时无需释放资源,开销小,速度快。

UDP协议通信场景

语音通话,视频会话等。

UDP通信

使用UDP通信实现发送消息、接收消息(一发一收)

package com.itheima.udp.demo01;

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

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

        byte[] bytes = "UDP协议数据发送测试".getBytes();
        /*
        创建数据包对象
            public DatagramPacket(byte buf[], int length,
                          InetAddress address, int port) {}
          参数一:数据字节数组,参数二:发送长度,参数三:对方IP地址,参数四:对方端口号
         */
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),9999);

        //发送数据
        socket.send(packet);
        System.out.println("数据已发送");

        socket.close();
    }
}
package com.itheima.udp.demo01;

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

/**
 * 服务端
 */
public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("=====服务端启动=====");
        //创建接收端对象
        DatagramSocket socket = new DatagramSocket(9999);

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

        //等待接收数据
        System.out.println("等待接收数据");
        socket.receive(packet);

        //取出数据
        String s = new String(bytes);
        System.out.println("接收到数据:"+s);
        System.out.println("对方IP地址:"+packet.getAddress());
        System.out.println("对方端口:"+packet.getPort());

        socket.close();

    }
}

使用UDP通信实现发送消息、接收消息(多发多收)

package com.itheima.udp.demo02;

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

/**
 * 服务端 多发多收
 */
public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("=====服务端启动=====");
        //创建接收端对象
        DatagramSocket socket = new DatagramSocket(9999);

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

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

            //取出数据
            String s = new String(bytes);
            System.out.println("接收到来自IP地址为"+packet.getAddress()+",端口为:"+packet.getPort()+"的消息:"+s);
        }
    }
}
package com.itheima.udp.demo02;

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

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

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入消息:");
            String s = sc.nextLine();
            if ("exit".equals(s)) {
                socket.close();
                System.out.println("拜拜");
                break;
            }
            //创建数据包对象
            byte[] bytes = s.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),9999);

            //发送数据
            socket.send(packet);
            System.out.println("消息已发送");
        }
    }
}

UDP广播

package com.itheima.udp.demo03broadcast;

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

/**
 * 发送端 广播
 * 发送端目的IP使用广播IP:"255.255.255.255"
 * 同一网段下其他主机使用对应端口即可接收广播消息
 */
public class Client {
    public static void main(String[] args) throws Exception {
        System.out.println("=======客户端启动======");
        //创建发送端对象,发送端自带默认端口号
        DatagramSocket socket = new DatagramSocket();

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入广播消息:");
            String s = sc.nextLine();
            if ("exit".equals(s)) {
                socket.close();
                System.out.println("拜拜");
                break;
            }
            //创建数据包对象
            byte[] bytes = s.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("255.255.255.255"),9999);

            //发送数据
            socket.send(packet);
            System.out.println("消息已发送");
        }
    }
}
package com.itheima.udp.demo03broadcast;

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

/**
 * 服务端 接收广播消息
 */
public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("=====服务端启动=====");
        //创建接收端对象
        DatagramSocket socket = new DatagramSocket(9999);

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

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

            //取出数据
            String s = new String(bytes);
            System.out.println("接收到来自IP地址为"+packet.getAddress()+",端口为:"+packet.getPort()+"的消息:"+s);
        }
    }
}

UDP组播

package com.itheima.udp.demo04multicast;

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

/**
 * 发送端 组播
 * 发送端目的IP使用组播IP:"224.0.0.0"-"239.255.255.255"并指定端口
 * 同一网段下其他主机注册该IP以及端口即可接收组播消息
 */
public class Client {
    public static void main(String[] args) throws Exception {
        System.out.println("=======客户端启动======");
        //创建发送端对象,发送端自带默认端口号
        DatagramSocket socket = new DatagramSocket();

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入组播消息:");
            String s = sc.nextLine();
            if ("exit".equals(s)) {
                socket.close();
                System.out.println("拜拜");
                break;
            }
            //创建数据包对象
            byte[] bytes = s.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("224.2.2.2"),9999);

            //发送数据
            socket.send(packet);
            System.out.println("消息已发送");
        }
    }
}
package com.itheima.udp.demo04multicast;

import java.net.*;

/**
 * 服务端 接收广播消息
 */
public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("=====服务端启动=====");
        //创建接收端对象
        MulticastSocket socket = new MulticastSocket(9999);
//        socket.joinGroup(InetAddress.getByName("224.2.2.2"));这种写法从JDK14开始过时
        /**
         public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
         参数一:组播IP地址和端口
         参数二:接收指定网段里的组播消息
         */
        socket.joinGroup(new InetSocketAddress(InetAddress.getByName("224.2.2.2"),9999),NetworkInterface.getByInetAddress(InetAddress.getLocalHost()));

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

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

            //取出数据
            String s = new String(bytes);
            System.out.println("接收到来自IP地址为"+packet.getAddress()+",端口为:"+packet.getPort()+"的消息:"+s);
        }
    }
}

TCP通信

使用TCP通信实现发送消息、接收消息(一发一收)

客户端代表类:Socket类

服务端代表类:ServerSocket类

客户端类
package com.itheima.tcp.demo01socket;

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

/**
 * 发送端  一发一收
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("客户端已启动");
        try {
            //创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
            Socket socket = new Socket("127.0.0.1", 8888);

            //从管道中获取一个字节输出流,用于发送数据
            OutputStream os = socket.getOutputStream();

            //将低级字节输出流封装为打印流
            PrintStream ps = new PrintStream(os);

            //发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
            ps.println("这是一条TCP测试消息");
            ps.flush();
            System.out.println("发送成功");

            //关闭资源,不建议关闭
//            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}
服务端类
package com.itheima.tcp.demo01socket;

import java.io.BufferedReader;
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) {
        System.out.println("服务端已启动");
        try {
            //注册端口
            ServerSocket serverSocket = new ServerSocket(8888);

            //调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
            Socket socket = serverSocket.accept();

            //从Socket管道中获取一个字节输入流,用于接收数据
            InputStream is = socket.getInputStream();
            //将低级字节输入流封装成缓冲字符输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            //接收数据
            String s;
            if ((s = br.readLine())!=null){
                System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用TCP通信实现发送消息、接收消息(多发多收,服务端与多个客户端通信)

客户端类
package com.itheima.tcp.demo02socket;

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

/**
 * 客户端  多发多收
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("客户端已启动");
        try {
            //创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
            Socket socket = new Socket("127.0.0.1", 8888);

            //从管道中获取一个字节输出流,用于发送数据
            OutputStream os = socket.getOutputStream();

            //将低级字节输出流封装为打印流
            PrintStream ps = new PrintStream(os);

            //发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请输入消息:");
                String s = sc.nextLine();
                ps.println(s);
                ps.flush();
                System.out.println("发送成功");
            }

            //关闭资源,不建议关闭
//            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
服务端类
package com.itheima.tcp.demo02socket;


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

/**
 * 服务端  实现服务端与多个客户端通信
 */
public class Server {
    public static void main(String[] args) {
        System.out.println("服务端已启动");
        try {
            //注册端口
            ServerSocket serverSocket = new ServerSocket(8888);

            //主线程使用死循环等待客户端连接
            while (true) {
                //调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
                Socket socket = serverSocket.accept();
                System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户上线了");
                //创建子线程接收客户端消息
                new SocketReaderThread(socket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
线程类
package com.itheima.tcp.demo02socket;

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

public class SocketReaderThread extends Thread {
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从Socket管道中获取一个字节输入流,用于接收数据
            InputStream is = socket.getInputStream();
            //将低级字节输入流封装成缓冲字符输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            //接收数据
            String s;
            while ((s = br.readLine())!=null){
                System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
            }
        } catch (Exception e) {
            //当客户端关闭后,服务端线程会抛出异常同步关闭,以此判定客户端下线
            System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户下线了");
        }
    }
}

使用线程池优化服务端与多个客户端通信,解决并发问题

客户端
package com.itheima.tcp.demo03socket;

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

/**
 * 客户端  多发多收
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("客户端已启动");
        try {
            //创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
            Socket socket = new Socket("127.0.0.1", 8888);

            //从管道中获取一个字节输出流,用于发送数据
            OutputStream os = socket.getOutputStream();

            //将低级字节输出流封装为打印流
            PrintStream ps = new PrintStream(os);

            //发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请输入消息:");
                String s = sc.nextLine();
                ps.println(s);
                ps.flush();
                System.out.println("发送成功");
            }

            //关闭资源,不建议关闭
//            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
服务端
package com.itheima.tcp.demo03socket;

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

/**
 * 服务端  使用线程池优化实现服务端与多个客户端通信
 */
public class Server {
    //定义一个线程池
    private static ExecutorService pool = new ThreadPoolExecutor(3,5,3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

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

            //主线程使用死循环等待客户端连接
            while (true) {
                //调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
                Socket socket = serverSocket.accept();
                System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户上线了");
                //创建线程任务并执行
                pool.execute(new SocketReaderRunnable(socket));
            }
        } catch (Exception e) {
            System.out.println("人满了,别来了");
        }
    }
}
线程任务类
package com.itheima.tcp.demo03socket;

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

public class SocketReaderRunnable implements Runnable{
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从Socket管道中获取一个字节输入流,用于接收数据
            InputStream is = socket.getInputStream();
            //将低级字节输入流封装成缓冲字符输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            //接收数据
            String s;
            while ((s = br.readLine())!=null){
                System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
            }
        } catch (Exception e) {
            //当客户端关闭后,服务端线程会抛出异常同步关闭,以此判定客户端下线
            System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户下线了");
        }
    }
}

实现TCP即时通信

客户端类
package com.itheima.tcp.demo04socket;

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

/**
 * 客户端  多发多收
 * 即时通信,客户端可收取来自其他客户端的消息
 */
public class Client {
    public static void main(String[] args) {
        System.out.println("客户端已启动");
        try {
            //创建Socket通信管道,请求服务端连接,参数一:服务器的IP,参数二:服务器端口
            Socket socket = new Socket("192.168.90.56", 8888);

            //创建一个子线程用于随时接收服务端的消息
            new SocketReaderThread(socket).start();

            //从管道中获取一个字节输出流,用于发送数据
            OutputStream os = socket.getOutputStream();

            //将低级字节输出流封装为打印流
            PrintStream ps = new PrintStream(os);

            //发送数据,这里发送的是一行消息,服务端应该同样接收一行消息,格式要一致
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请输入消息:");
                String s = sc.nextLine();
                ps.println(s);
                ps.flush();
                System.out.println("发送成功");
            }

            //关闭资源,不建议关闭
//            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
客户端接收数据线程类
package com.itheima.tcp.demo04socket;

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

public class SocketReaderThread extends Thread {
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从Socket管道中获取一个字节输入流,用于接收数据
            InputStream is = socket.getInputStream();
            //将低级字节输入流封装成缓冲字符输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            //接收数据
            String s;
            while ((s = br.readLine())!=null){
                System.out.println(socket.getRemoteSocketAddress());
                System.out.println("收到消息:"+s);
            }
        } catch (Exception e) {
            System.out.println("你被服务端断开了");
        }
    }
}
服务端类
package com.itheima.tcp.demo04socket;


import sun.util.resources.cldr.zh.TimeZoneNames_zh;

import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.*;

/**
 * 服务端  使用线程池优化实现服务端与多个客户端通信
 */
public class Server {
    //定义一个线程池
    private static ExecutorService pool = new ThreadPoolExecutor(3,5,3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

    //定义一个集合存储所有在线的Socket线程通道
    public static ArrayList<Socket> allOnlineSockets = new ArrayList<>();

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

            //主线程使用死循环等待客户端连接
            while (true) {
                //调用accept方法,等待客户端的socket连接请求,建立Socket通信管道
                Socket socket = serverSocket.accept();
                System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户上线了");
                allOnlineSockets.add(socket);
                //创建线程任务并执行
                pool.execute(new SocketReaderRunnable(socket));
            }
        } catch (Exception e) {
            System.out.println("人满了,别来了");
            e.printStackTrace();
        }
    }
}
线程任务类
package com.itheima.tcp.demo04socket;

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

public class SocketReaderRunnable implements Runnable{
    private Socket socket;

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

    @Override
    public void run() {
        try {
            //从Socket管道中获取一个字节输入流,用于接收数据
            InputStream is = socket.getInputStream();
            //将低级字节输入流封装成缓冲字符输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            //接收数据
            String s;
            while ((s = br.readLine())!=null){
                System.out.println("收到来自IP地址为:"+socket.getRemoteSocketAddress()+"的消息:"+s);
                //端口转发
                sendMsgToAll(s,socket.getRemoteSocketAddress());
            }
        } catch (Exception e) {
            //当客户端关闭后,服务端线程会抛出异常同步关闭,以此判定客户端下线
            System.out.println("IP地址为:"+socket.getRemoteSocketAddress()+"的用户下线了");
            Server.allOnlineSockets.remove(socket);
        }
    }

    private void sendMsgToAll(String s, SocketAddress remoteSocketAddress) throws Exception {
        for (Socket socket : Server.allOnlineSockets) {
            if (!remoteSocketAddress.equals(socket.getRemoteSocketAddress())){
                PrintStream ps = new PrintStream(socket.getOutputStream());
                ps.println(s);
                ps.flush();
            }
        }
    }
}

BS模式模拟

服务端类
package com.itheima.tcp.demo05socket;


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

/**
 * 服务端  使用线程池优化
 *
 */
public class BSServer {
    //定义一个线程池
    private static ExecutorService pool = new ThreadPoolExecutor(3,5,3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

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

            //主线程使用死循环等待客户端连接
            while (true) {
                //调用accept方法,等待浏览器的socket连接请求,建立Socket通信管道
                Socket socket = serverSocket.accept();
                //创建线程任务并执行
                pool.execute(new SocketReaderRunnable(socket));
            }
        } catch (Exception e) {
            System.out.println("人满了,别来了");
            e.printStackTrace();
        }
    }
}
线程任务类
package com.itheima.tcp.demo05socket;

import com.itheima.tcp.demo04socket.Server;

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

public class SocketReaderRunnable implements Runnable{
    private Socket socket;

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

    @Override
    public void run() {
        try {
            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:yellow;font-size:90px'>又快睡着了吧林总</span>");
            ps.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值