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

2023-10-27

网络通信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() + " 离开了!!!");
        }
    }
}

在这里插入图片描述

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网络通信,UDP通信,TCP通信 的相关文章

随机推荐

  • Centos8安装MySQL

    受苦于博客总是过于老旧 安装时总会出现版本包已经删除的情况而且步骤总是各式各样难以理解 无奈之下还是官网靠谱 于是这篇博客以官网方法为基准 方便以后安装的时候可以直接复制命令 一 官网教程 https dev mysql com doc r
  • STM32毕业设计选题汇总

    文章目录 1前言 2 STM32 毕设课题 3 如何选题 3 1 不要给自己挖坑 3 2 难度把控 3 3 如何命名题目 1前言 更新单片机嵌入式选题后 不少学弟学妹催学长更新STM32和C51选题系列 感谢大家的认可 来啦 以下是学长亲手
  • python通过docker打包执行

    背景 正常情况下 python脚本执行需要安装有python环境 那python环境虽然也可以通过移植的方法来安装 那总归是比较麻烦的 下面通过docker打包的方式来执行python脚本 1 安装python镜像 准备两个文件即可 doc
  • 前端LayUI框架快速上手实现登入注册

    目录 一 Layui简介 1 什么是LayUI 2 LayUI的特点 二 LayUI入门 1 LayUI下载 2 LayUI入门使用 2 1 在web项目中导入LayUI文件中的layui文件 2 2 在JSP页面引入css js文件 2
  • linux建立虚拟内存,如何在Linux环境下建立虚拟内存

    虚拟内存是将硬盘规划出一个区间用来读取数据的空间 但是有很多用户们都不知道Linux环境下如何建立虚拟内存 那么现在我们就一起跟小编去看看具体内容吧 在Linux 下就是建立swap file 基本步骤 先建立swap这个装置或是档案后 将
  • Java程序员到架构师的推荐阅读书籍

    Java程序员到架构师的推荐阅读书籍 作为Java程序员来说 最痛苦的事情莫过于可以选择的范围太广 可以读的书太多 往往容易无所适从 我想就我自己读过的技术书籍中挑选出来一些 按照学习的先后顺序 推荐给大家 特别是那些想不断提高自己技术水平
  • Python文件读写

    Python的文件操作函数 open filename mode 文件打开模式 执行操作 r 以只读方式打开 默认 w 以写入的方式打开文件 会覆盖已经存在的文件 x 如果指定文件已经存在 使用此模式打开将引发异常 a 以写入模式打开 如果
  • 分治法求解汉诺塔问题

    汉诺塔问题简介 汉诺塔 又称河内塔 问题是源于印度一个古老传说的益智玩具 大梵天创造世界的时候做了三根金刚石柱子 在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘 大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上 并且规定
  • GD32E230使用J-LINK下载调试问题

    1 无法识别到GD32的芯片 j link的版本要V9的才行 也就是下图的HW版本V9 4 之前是V7一直无法识别 换成V9的j link之后就可以了 2 打开J link的setting时弹出盗版警告 Warning the connec
  • Dialog居中显示

    最新使用Dialog时 发现在以下低版本系统中会出现Dialog弹窗在左上角显示的情况 搜索了一下 发现了这个方法 记录一下 dialog 居中显示 Window window dialog getWindow if dialog null
  • C++中私有变量的值想怎么改就怎么改

    这应该算是C 的一个不足吧 C 是优秀的编程语言 但不是完美的 include
  • Mybatis-plus中,如何提前获取实体类用雪花算法生成的ID?

    Mybatis plus中 通过设置 TableId可以让Mybatis plus自动为我们生成雪花算法的ID号 该ID号是一个长整型数据 非常方便 但是雪花算法的ID号是在Insert执行的时候生成的 我们在Insert执行前是不知道En
  • 论文期刊分类学习记录

    SCI主要偏重理论性研究 EI偏工程应用 SCI源刊 gt SCI会议 gt EI源刊 影响因子较好 gt 既是中文核心又是EI源刊的期刊 gt EI源刊 影响因子一般 gt EI会议 权威会议 gt 中文核心期刊 南大核心 CSCS gt
  • SQL开窗函数(窗口函数)详解

    一 什么是开窗函数 开窗函数 分析函数 over 开窗函数也叫分析函数 有两类 一类是聚合开窗函数 一类是排序开窗函数 开窗函数的调用格式为 函数名 列名 OVER partition by 列名 order by列名 如果你没听说过开窗函
  • java8 list根据实体单字段、多字段分组。去重

    Map
  • boost静态链接库和c++/clr不兼容问题:未能加载文件或程序集,不是有效的Win32应用程序。

    项目上遇到的问题 c 编写的类使用托管c 包装成dll提供给c 项目使用 c 需要使用boost clr 项目目标平台都是win32 x86 开发环境win10 x64系统 vs2013 Net Framework 4 0 boost 1
  • Node之加密与解密处理

    crypto模块概述 在Node js中 使用OpenSSL类库作为其内部实现加密与解密处理的基础手段 这是因为目前OpenSSL已经成为了一个经过严格测试的可靠的加密与解密算法的实现工具 在Node js中 OpenSSL类库被封装在cr
  • 以太坊智能合约编程入门(一)

    原文地址 https medium com ConsenSys a 101 noob intro to programming smart contracts on ethereum 695d15c1dab4 1 ABBewYWJfdIFh
  • SMBMS项目

    一 准备工作 1 基本架构 2 在数据库中创建对应的表 对应数据库代码如下 CREATE DATABASE smbms USE smbms DROP TABLE IF EXISTS smbms address CREATE TABLE sm
  • 网络通信,UDP通信,TCP通信

    网络通信3要素 要素1 IP地址 IP地址操作类 InetAddress package com heima test import java net InetAddress import java net UnknownHostExcep