Java Socket:单线程/多线程/线程池ServerSocket编程

来源:互联网 发布:单片机无线模块程序 编辑:程序博客网 时间:2024/05/16 23:33

  Socket将网络抽象成可读写的字节流,其对用户掩藏了底层繁杂的细节。Java使用Socket对象实现客户端网络流程:请求连接、发/收数据、关闭链接;使用ServerSocket对象实现服务端网络流程:绑定端口/本地接口、侦听请求、接受请求、收/发数据和关闭连接。下面总结了模拟daytime协议服务端的程序,分别用单线程、多线程和固定线程池的方式实现,每种实现方式在一切无视应用场景的情形下都难分伯仲,笔者看来对于简单的daytime服务器单线程实现足够,但是任何场景下都不要使用无限制线程数量的实现方式。

  • SingleThreadServer.java 单线程服务方式:
import java.io.IOException;import java.io.OutputStreamWriter;import java.io.Writer;import java.net.ServerSocket;import java.net.Socket;import java.util.Date;/** * Created by Cheney Hwang on 2017/5/1. * 简短协议适用于单线程短连接,处理快无额外开销 */public class SingleThreadServer {    public final static int PORT=5555;    public static void main(String[] args){        try(ServerSocket server=new ServerSocket(PORT)){            while(true){                try(Socket socket=server.accept()){                    Writer out=new OutputStreamWriter(socket.getOutputStream(),"ASCII");                    Date now=new Date();                    out.write(now.toString()+"\r\n");                    //时间协议,添加不依赖于平台的换行符                    out.flush();                    out.close();                }catch (IOException ex){                    //忽略连接异常                }            }        }catch (IOException ex){//端口占用或者无权使用将抛出异常            System.err.println(ex);        }    }}
  • MultiThreadServer.java 无限制数量多线程服务方式:
import java.io.IOException;import java.io.OutputStreamWriter;import java.io.Writer;import java.net.ServerSocket;import java.net.Socket;import java.util.Date;/** * Created by Cheney Hwang on 2017/5/1. * 每个客户连接请求都生成一个处理线程,可以防止慢客户端阻塞所有其他客户端 * 这种服务方式现实是不可能采用的,容易遭受DOS攻击 */public class MultiThreadServer {    public final static int PORT=5555;    public static void main(String[] args){        try(ServerSocket server=new ServerSocket(PORT)){            while(true) {                try {                    Socket client = server.accept();                    Thread task = new TimeThread(client);                    task.start();                } catch (IOException ex) {                    //忽略连接异常                }            }        }catch (IOException ex){//端口占用或者无权使用将抛出异常            System.err.println(ex);        }    }    private static class TimeThread extends Thread{        private Socket client;        public TimeThread(Socket client){            this.client=client;        }        @Override        public void run(){            try{                Writer out=new OutputStreamWriter(client.getOutputStream());                Date now=new Date();                out.write(now.toString()+"\r\n");                //时间协议,添加不依赖于平台的换行符                out.flush();                out.close();            }catch (IOException ex){                System.err.println(ex);            }finally {                try {                    client.close();                }catch (IOException ex){                    //忽略                }            }        }    }}
  • FixedPoolServer.java 固定数量线程池服务方式:
import java.io.IOException;import java.io.OutputStreamWriter;import java.io.Writer;import java.net.ServerSocket;import java.net.Socket;import java.util.Date;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * Created by Cheney Hwang on 2017/5/1. * 固定线程数量的服务方式可以拒绝客户端连接请求,但是自身不会崩溃 */public class FixedPoolServer {    public final static int PORT = 5555;    public static void main(String[] args) {        ExecutorService pool = Executors.newFixedThreadPool(50);        //固定大小线程池        try (ServerSocket server = new ServerSocket(PORT)) {            while (true) {                try {                    Socket client = server.accept();                    Callable<Void> task = new TimeThread(client);                    pool.submit(task);                } catch (IOException ex) {                    //忽略连接异常                }            }        } catch (IOException ex) {//端口占用或者无权使用将抛出异常            System.err.println(ex);        }    }    private static class TimeThread implements Callable<Void> {        private Socket client;        public TimeThread(Socket client) {            this.client = client;        }        @Override        public Void call() {            try {                Writer out = new OutputStreamWriter(client.getOutputStream());                Date now = new Date();                out.write(now.toString() + "\r\n");                //时间协议,添加不依赖于平台的换行符                out.flush();                out.close();            } catch (IOException ex) {                System.err.println(ex);            } finally {                try {                    client.close();                } catch (IOException ex) {                    //忽略                }            }            return null;        }    }}

  • 下面是示例客户端:
import java.io.IOException;import java.io.InputStreamReader;import java.io.Reader;import java.net.Socket;/** * Created by Cheney Hwang on 2017/5/1. */public class Client {    public final static String HOST="localhost";    public final static int PORT=5555;    public static void main(String[] args){        try(Socket client=new Socket(HOST,PORT)){//指定服务器的地址和端口            Reader in=new InputStreamReader(client.getInputStream());            int c;            StringBuilder builder=new StringBuilder();            while ((c=in.read())!=-1){                builder.append((char)c);            }            System.out.println(builder.toString());            in.close();        }catch (IOException ex){            System.err.println("Cant connect to server!");        }    }}
0 0
原创粉丝点击