zoukankan      html  css  js  c++  java
  • JAVA I/O(五)多线程网络Socket和ServerSocket

    上篇文章介绍了Socket和ServerSocket简单使用和源码,服务器端会对每个客户端请求创建一个线程,为使服务器端能同时处理多个客户端请求,可以采用多线程的方式。本文仅对实例进行简单记录,如下。

    服务器端

    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class MultiJabberServer {
        
        static final int PORT = 8080;
    
        public static void main(String[] args) throws IOException{
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("Server Started");
            try {
                while(true) {
                    Socket socket = serverSocket.accept();
                    try {
                        new ServeOneJabber(socket);
                    } catch (IOException e) {
                        // If it fails, close the socket,
                        // otherwise the thread will close it:
                        socket.close();
                    }
                }
            } finally {
                serverSocket.close();
            }
        }
    }

     while循环获取连接,并构造ServerOneJabber,启动线程处理客户端交互。

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.Socket;
    
    public class ServeOneJabber extends Thread{
        
        private Socket socket;
        
        private BufferedReader in;
        
        private PrintWriter out;
        
        public ServeOneJabber(Socket socket) throws IOException{
            this.socket = socket;
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
            start();
        }
        
        public void run() {
            try {
                while (true) {
                    String str = in.readLine();
                    if ("END".equals(str)) {
                        break;
                    }
                    System.out.println("Echoing: " + str);
                    out.println("Got: " + str);
                }
                System.out.println(socket + ", seesion closing....");
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } finally {
                try {
                    socket.close();
                } catch (Exception e2) {
                    System.out.println("Socket not closed");
                }
            }
        }
    }

     原理与上篇文章一样,获取输入输出流,对请求信息进行处理和响应。

    客户端

    import java.io.IOException;
    import java.net.InetAddress;
    
    public class MultiJabberClient {
        
        static final int MAX_THREADS = 40;
    
        public static void main(String[] args) throws IOException, InterruptedException{
            InetAddress addr = InetAddress.getByName(null);
            for(int i = 0; i < MAX_THREADS; i++) {
                new JabberClientThread(addr);
                Thread.sleep(100);
            }
    //        while(true) {
    //            if(JabberClientThread.threadCount() < MAX_THREADS) {
    //                new JabberClientThread(addr);
    //            }
    //            Thread.sleep(100);
    //        }
        }
    }

    构造线程JabberClientThread,构建Socket,与服务器端连接。

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class JabberClientThread extends Thread{
        private Socket socket;
        private BufferedReader in;
        private PrintWriter out;
        private static int counter = 0;
        private int id = counter++;
        private static int threadCount = 0;
        
        public static int threadCount() {
            return threadCount;
        }
    
        public JabberClientThread(InetAddress addr){
            System.out.println("Making client " + id);
            threadCount++;
            try {
                socket = new Socket(addr, MultiJabberServer.PORT);
            } catch (IOException e) {
                // If the creation of the socket fails,
                // nothing needs to be cleaned up.
                System.out.println("Socket failed");
                return;
            }
            try {
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                start();
            } catch (IOException e) {
                // The socket should be closed on any
                // failures other than the socket
                // constructor:
                try {
                    socket.close();
                } catch (IOException e2) {
                    System.err.println("Socket not closed");
                }
                
            }
        }
        
        public void run() {
            try {
                for(int i = 0; i < 5; i++) {
                    out.println("Client " + id + ":" + i);
                    String str = in.readLine();
                    System.out.println(str);
                }
                out.println("END");
            } catch (IOException e) {
                System.err.println("IO Exception");
            } finally {
                try {
                    socket.close();
                } catch (IOException e2) {
                    System.err.println("Socket not closed");
                }
                threadCount--;
            }
        }
    }

     其中包含成员属性id和threadCount,每创建一个线程,id递增(采用类成员控制);threadCount作为线程数量的记录,线程创建时加一,结束时减一。

    运行结果如下

    服务器端:

    Server Started
    Echoing: Client 0:0
    Echoing: Client 0:1
    Echoing: Client 0:2
    Echoing: Client 0:3
    Echoing: Client 0:4
    Socket[addr=/127.0.0.1,port=42998,localport=8080], seesion closing....
    Echoing: Client 1:0
    Echoing: Client 1:1
    Echoing: Client 1:2
    Echoing: Client 1:3
    Echoing: Client 1:4
    Socket[addr=/127.0.0.1,port=43000,localport=8080], seesion closing....
    ......
    Echoing: Client 39:0
    Echoing: Client 39:1
    Echoing: Client 39:2
    Echoing: Client 39:3
    Echoing: Client 39:4
    Socket[addr=/127.0.0.1,port=43076,localport=8080], seesion closing....

     客户端:

    Making client 0
    Got: Client 0:0
    Got: Client 0:1
    Got: Client 0:2
    Got: Client 0:3
    Got: Client 0:4
    Making client 1
    Got: Client 1:0
    Got: Client 1:1
    Got: Client 1:2
    Got: Client 1:3
    Got: Client 1:4
    .....
    Making client 39
    Got: Client 39:0
    Got: Client 39:1
    Got: Client 39:2
    Got: Client 39:3
    Got: Client 39:4
  • 相关阅读:
    php实现cookie加密解密
    三个php加密解密算法
    一个经典的PHP加密解密算法
    Webpack 核心模块 tapable 解析(转)
    详解基于vue,vue-router, vuex以及addRoutes进行权限控制
    编写一个插件
    详解css3 pointer-events(阻止hover、active、onclick等触发事件来
    Dockerfile HEALTHCHECK详解
    Dockerfile 指令 WORKDIR介绍
    NPM私有包部署到私有仓库
  • 原文地址:https://www.cnblogs.com/shuimuzhushui/p/10339425.html
Copyright © 2011-2022 走看看