行业资讯 2025年08月6日
0 收藏 0 点赞 949 浏览 7884 个字
摘要 :

文章目录 1、Java项目Socket编程案例 第1步:创建服务端 第2步:创建客户端 第3步:创建测试类 优化:使用线程池去异步处理 1)新增HandleSocketRunnable线程 2)修……




  • 1、Java项目Socket编程案例
    • 第1步:创建服务端
    • 第2步:创建客户端
    • 第3步:创建测试类
  • 优化:使用线程池去异步处理
    • 1)新增HandleSocketRunnable线程
    • 2)修改Server线程类
  • 2、Socket编程案例应用到Java web项目
    • 第1步:创建监听器
    • 第2步:配置web.xml

    最近Java潘老师在协同底层项目开发web端需要使用到socket与其通信,实现消息传输,于是重拾那遗忘久矣的Java Socket网络编程技术。还记得当时学习Java Socket编程例子的时候是写了一个在线聊天室,有单聊有群聊,玩的的不亦乐乎,真正能体会到学Java技术原来这么有意思,不过今天潘老师就总结下最基础入门的Java Socket编程案例,并写把它融入到Java Web项目中,注意不是websocket哦~

    1、Java项目Socket编程案例

    我们目前的需求很简单,就是新建一个Java项目,然后有客户端,有服务端,客户端可以给服务端发消息,服务端收到消息然后返回一个响应给客户端。本案例基于TCP协议,如果想使用UDP的可以自行百度去哦。

    第1步:创建服务端

    由于服务端中有个accept方法是阻塞方法,用来监听端口等待客户端发送消息,所以我们服务端要单独开一个线程去监听端口,否则运行时会阻塞主线程,导致程序堵死,下面就是潘老师写的一个简单的服务端代码:

    package com.panziye.socket;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server extends Thread {
        // 服务端对象
        private ServerSocket serverSocket;
        // 默认监听8877端口
        private int port = 8877;
    
        // 构造方法,初始化服务端
        public Server() {
            try {
                // 创建Socket服务器对象,监听8877端口
                serverSocket = new ServerSocket(port);
                System.out.println("ServerSocket创建了....");
            } catch (Exception e) {
                System.out.println("ServerSocket创建出错....");
            }
    
        }
    
        // 重写run方法
        public void run() {
            System.out.println("服务端启动了,等待客户端发送消息....");
            // 循环监听,直到线程中断为止
            while(!this.isInterrupted()){
                try {
                    // accept是阻塞方法,等待客户端发消息
                    Socket socket = serverSocket.accept();
                    if(socket != null && !socket.isClosed()){
                        // 处理socket消息
                        handleSocket(socket);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
    
        // 处理服务端接收到的socket消息
        private void handleSocket(Socket socket) {
            InputStream is = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            OutputStream os = null;
            PrintWriter pw = null;
            StringBuffer result = new StringBuffer();
            try {
                is = socket.getInputStream();
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);
    
                String info = null;
                // 从流中读取客户端消息
                while ((info = br.readLine()) != null) {
                    result.append(info);
                }
                // 输出消息
                System.out.println("我是服务器,客户端说:" + result);
                socket.shutdownInput();
                // 给客户端响应消息
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.write("客户端你好,欢迎访问潘老师博客:https://www.panziye.com");
    
                pw.flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 关闭资源
                try {
                    if (pw != null)
                        pw.close();
                    if (os != null)
                        os.close();
                    if (br != null)
                        br.close();
                    if (isr != null)
                        isr.close();
                    if (is != null)
                        is.close();
                    if (socket != null)
                        socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 关闭socket
         */
        public void closeSocketServer(){
            try {
                if(serverSocket != null && !serverSocket.isClosed()){
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    该服务端主要监听本机的8877端口,记得处理完客户端消息后一定要关闭IO流和socket

    第2步:创建客户端

    客户端比较简单,主要就是和服务端建立连接,然后可以像服务端发送消息,并获取服务端返回的消息。例子代码如下:

    package com.panziye.socket;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    
    public class Client {
        // 主机地址
        private String host = "localhost";
        // 端口
        private int port = 8877;
    
        /**
         * 客户端向服务端发送消息
         */
        public String sendMessage(String msg) {
            // 响应结果
            StringBuffer result = new StringBuffer();
            BufferedReader br = null;
            InputStream is = null;
            OutputStream os = null;
            PrintWriter pw = null;
            Socket socket = null;
            try {
                // 和服务器创建连接
                socket = new Socket(host,port);
                System.out.println("和服务器已建立连接....");
                // 要发送给服务器的信息
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                // 给服务端发msg
                pw.write(msg);
                pw.flush();
                
                socket.shutdownOutput();
                
                // 从服务器接收的信息
                is = socket.getInputStream();
                br = new BufferedReader(new InputStreamReader(is));
                String info = null;
                while((info = br.readLine())!=null){
                    result.append(info);
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                // 关闭流和socket
                try {
                    if(br != null)
                        br.close();
                    if(is != null)
                        is.close();
                    if(os != null)
                        os.close();
                    if(pw != null)
                        pw.close();
                    if(socket != null)
                        socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return result.toString();
        }
    }
    

    第3步:创建测试类

    最后我们创建一个测试类,来测试效果,具体代码如下:

    package com.panziye.socket;
    
    public class SocketTest {
        public static void main(String[] args) {
            // 创建服务端线程并启动
            new Server().start();
            // 休眠3s等待服务端线程启动成功
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 创建客户端并发消息
            String response = new Client().sendMessage("你好潘老师...");
            System.out.println("服务端响应:"+response);
        }
    
    }
    

    最后我们运行,发现可以成功建立连接,发送消息,获得响应。查看控制台打印结果具体如图:
    Java Socket编程例子并应用到Java Web项目

    优化:使用线程池去异步处理

    为了提高效率,我们可以将handleSocket方法也封装在一个Runnable线程中,然后可以每次accept到socket消息时就,交给线程池去处理即可,这样就可以避免阻塞情况,具体修改的代码如下。

    1)新增HandleSocketRunnable线程

    package light.mvc.thread;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    
    public class HandleSocketRunnable implements Runnable {
        
        private Socket socket = null;
        private InputStream is=null;
        private InputStreamReader isr=null;
        private BufferedReader br=null;
        private OutputStream os=null;
        private PrintWriter pw=null;
        
        public HandleSocketRunnable(Socket socket) {
            this.socket = socket;
        }
     
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
            // 获取消息
            String message = getMessage();
            // 处理message
            System.out.println(message);
            // 发送响应
            boolean flag= responseMessage("响应消息");
            // 关闭socket
            closeSocket();
        }
    
        // 获取客户端消息
        private String getMessage() {
            
            StringBuffer result = new StringBuffer();
            try {
                is = socket.getInputStream();
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);
                String info = null;
                while((info=br.readLine())!=null){
                    result.append(info);
                }
                socket.shutdownInput();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result.toString();
        }
        // 给客户端返回响应
        private boolean responseMessage(String message) {
            OutputStream os=null;
            PrintWriter pw=null;
            try {
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.write(message);
                pw.flush();
            } catch (Exception e) {
                e.printStackTrace();
                 return false;
            }
            return true;
        }
        
        // 关闭socket
        private void closeSocket() {
            //关闭资源
            try {
                if(br!=null)
                    br.close();
                if(isr!=null)
                    isr.close();
                if(is!=null)
                    is.close();
                if(pw!=null)
                    pw.close();
                if(os!=null)
                    os.close();
                if(socket != null)
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
    

    2)修改Server线程类

    package com.panziye.socket;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Server extends Thread {
        // 服务端对象
        private ServerSocket serverSocket;
        // 创建定长线程池
        private ExecutorService executor = Executors.newFixedThreadPool(5);
        // 默认监听8877端口
        private int port = 8877;
    
        // 构造方法,初始化服务端
        public Server() {
            try {
                // 创建Socket服务器对象,监听8877端口
                serverSocket = new ServerSocket(port);
                System.out.println("ServerSocket创建了....");
            } catch (Exception e) {
                System.out.println("ServerSocket创建出错....");
            }
    
        }
    
        // 重写run方法
        public void run() {
            System.out.println("服务端启动了,等待客户端发送消息....");
            // 循环监听,直到线程中断为止
            while(!this.isInterrupted()){
                try {
                    // accept是阻塞方法,等待客户端发消息
                    Socket socket = serverSocket.accept();
                    if(socket != null && !socket.isClosed()){
                        // 线程池多线程处理接收的数据
                                executor.submit(new HandleSocketRunnable(socket));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
    
        /**
         * 关闭socket
         */
        public void closeSocketServer(){
            try {
                if(serverSocket != null && !serverSocket.isClosed()){
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    通过以上的代码修改我们就可以实现使用线程池去处理socket请求了,效率也会随之提高很多。

    2、Socket编程案例应用到Java web项目

    其实上面的代码如果你都理解了,那我们可以很轻松地将该案例应用到java web项目中,而难点就在于如何使服务端ServerThread随着web项目启动而启动。这里以Spring项目为例。

    第1步:创建监听器

    这里我们可以在Spring项目中新建一个监听器,实现ServletContextListener主要重写容器销毁和容器初始化方法:

    package com.panziye.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import com.panziye.socket.ServerThread;
    
    public class SocketServerListener implements ServletContextListener {
        
        private ServerThread serverThread;  
        
        /**
         * 销毁方法
         */
        @Override
        public void contextDestroyed(ServletContextEvent arg0) {
            if (serverThread != null && serverThread.isInterrupted()) {  
                serverThread.interrupt();  
            }  
        }
    
        /**
         * 初始化方法
         */
        @Override
        public void contextInitialized(ServletContextEvent arg0) {
            if(serverThread == null) {
                // 创建线程
                ServerThread serverThread= new ServerThread (null);
                // 设为守护线程
                serverThread.setDaemon(true);
                // 启动socket线程
                serverThread.start();
            }
            
        }
    }
    

    第2步:配置web.xml

    我们需要将创建好的监听器配置在web.xml中,具体如下:

    <listener>
        <listener-class>com.panziye.listener.SocketServerListener</listener-class>
    </listener>
    

    最后启动项目就会发现,Socket服务端线程随着项目启动而启动了。

    好了,以上就是Java Socket编程例子并应用到了Java Web项目中,其实里面的代码还有许多地方值得优化,你都学会了吗?

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/8090.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号