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

 

上一篇:mysqldump: Got error: 1102: Incorrect database nam


下一篇:day003注释、标识符、数据类型