java BIO实例——ServerSocket、Socket编程

在使用传统的ServerSocket和Socket的时候很多时候程序是会阻塞的比如serversocket.accept() , socket.getInputStream().read() 的时候都会阻塞

  • accept()方法除非等到客户端socket的连接或者被异常中断否则会一直等待下去
  • read()方法也是如此除非在输入流中有了足够的数据否则该方法也会一直等待下去知道数据的到来

在ServerSocket与Socket的方式中服务器端往往要为每一个客户端连接(socket)分配一个线程,而每一个线程都有可能处于长时间的阻塞状态中而过多的线程也会影响服务器的性能在JDK1.4引入了非阻塞的通信方式NIO这样使得服务器端只需要一个线程就能处理所有客户端socket的请求

 

【实例1:单机版】

1Server

public class Server{

 

publicstatic void main(String[] args) throws IOException {

//创建一个ServerSocket在端口4700监听客户请求

ServerSocketserver = new ServerSocket(5678);

/**

 * 使用accept()阻塞等待客户连接,有客户请求到来则产生一个Socket对象,并继续执行

 */

Socketsocket = server.accept();

 

//由Socket对象得到输入流,并构造相应的BufferedReader对象

BufferedReaderin = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

//由Socket对象得到输出流,并构造PrintWriter对象

             PrintWriter out =new PrintWriter(socket.getOutputStream());

       

            while (true) {

                 //阻塞读取客户端发送的数据、并向标准输出

            String str = in.readLine(); 

            System.out.println(str);

           

            //向客户端输出字符,并刷新输出流,使Client马上收到该字符串

            out.println("hasreceive...."); 

            out.flush(); 

           

           

            if(str.equals("end")) 

                break; 

          }

       

        out.close();//关闭socket输出流

        in.close();//关闭socket输入流

        socket.close();//关闭socket

        server.close();//关闭serverSocket

}

}

2Client

public class Client{

staticSocket server; 

 

publicstatic void main(String[] args) throws Exception{

//向本机的5678端口发出客户请求

      server= new Socket(InetAddress.getLocalHost(), 5678);

 

//由Socket对象得到输入流,并构造相应的BufferedReader对象

        BufferedReader in = newBufferedReader(new InputStreamReader(server.getInputStream()));

        //由Socket对象得到输出流,并构造PrintWriter对象

        PrintWriter out = newPrintWriter(server.getOutputStream());

       

        //由系统标准输入设备构造BufferedReader对象

        BufferedReader wt = newBufferedReader(new InputStreamReader(System.in)); 

        while (true) {

               //从标准输入读取

            String str = wt.readLine();

           

            //向服务器端输出字符,并刷新输出流,使server马上收到该字符串

            out.println(str); 

            out.flush();

           

           

            if (str.equals("end")){ 

                break; 

            } 

           System.out.println(in.readLine()); 

        }

       

        out.close();//关闭Socket输出流

        in.close();//关闭Socket输入流

        server.close();//关闭Socket

 

}

}

说明:上面代码,只能有一个客户端链接到服务器。一旦有一个客户端链接到了服务器,服务器代码就会一直处在while死循环中,和客户端通信,直到客户端退出。

 

【实例2:多线程版】

1ServerThread

public classServerThread extends Thread{

privateSocket socket; 

 

    public ServerThread(Socket s) { 

        this.socket = s; 

    }

   

    public void run() { 

        try {

               //构造socket的输入流

            BufferedReader in = newBufferedReader(new InputStreamReader(socket.getInputStream()));

            //根据socket构造输出流

            PrintWriter out = newPrintWriter(socket.getOutputStream()); 

            // Mutil User but can'tparallel 

 

            while (true) {

                   //读取客户端输入流中内容

                String str =in.readLine(); 

                System.out.println(str);

               

                //向客户端输出

                out.println("hasreceive...."); 

                out.flush();

               

                if(str.equals("end")) 

                    break; 

            }

            out.close();

            in.close();

            socket.close(); 

        } catch (IOException ex) { 

        } finally {

               

        } 

    } 

 

publicstatic void main(String[] args) throws IOException {

ServerSocketserver = new ServerSocket(5678);

while(true) { 

            //每一个客户端连接(server.accept())分配一个线程来处理

               ServerThread mc = new ServerThread(server.accept()); 

            mc.start(); 

        }

}

}

2)客户端代码同上;

3)说明:

  • 服务器一直处在死循环中,为每一个客户端连接分配一个线程,所以服务器可以接收多个客户端的请求;
  • 由于server.accept()read等方法是阻塞的,所以在每一个线程都有可能处于长时间的阻塞状态,这样当客户端大量连接服务器时,就会积累大量的线程(线程中也是一时半会无法执行结束);

你可能感兴趣的:(java)