高分!跪求在线等,关于ServerSocket返回超时问题

时间:2022-03-13 05:06:49
先看代码Socket服务端

public class Server {  
   
   public static void main(String args[]) throws IOException {  
      //为了简单起见,所有的异常信息都往外抛  
      int port = 8889;  
      //定义一个ServerSocket监听在端口8899上  
      ServerSocket server = new ServerSocket(port);  
      System.out.println("ServerSocket   kai shi");
      while (true) {  
         //server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的  
          System.out.println("accept   kai shi");
         Socket socket = server.accept();  
         //每接收到一个Socket就建立一个新的线程来处理它  
         new Thread(new Task(socket)).start();  
      }  
   }  
     
   /** 
    * 用来处理Socket请求的 
    */  
   static class Task implements Runnable {  
   
      private Socket socket;  
        
      public Task(Socket socket) {  
         this.socket = socket;  
      }  
        
      public void run() {  
         try {  
            handleSocket();  
         } catch (Exception e) {  
            e.printStackTrace();  
         }  
      }  
        
      /** 
       * 跟客户端Socket进行通信 
      * @throws Exception 
       */  
      private void handleSocket() throws Exception {  
       System.out.println("handleSocket!!!");
      //socket.setSoTimeout(2 * 1000);
         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));  
         StringBuilder sb = new StringBuilder();  
         String temp;  
         int index;   
         while ((temp=br.readLine()) != null) {  
          
//             if ((index = temp.indexOf("eof")) != -1) {//  
//              sb.append(temp.substring(0, index));  
//                 break;  
//             }  
            sb.append(temp);  
         }  
         System.out.println("客户端: " + sb);  
         //读完后写一句  
         Writer writer = new OutputStreamWriter(socket.getOutputStream(), "GBK");  
         writer.write("你好,客户端。");   
         writer.flush();  
         writer.close();  
         br.close();  
         socket.close();  
      }  
   }  
}  


再看客户端

public static void main(String[] args) throws Exception {
     String host = "127.0.0.1";  //要连接的服务端IP地址  
     int port = 8889;   //要连接的服务端对应的监听端口  
     //与服务端建立连接  
     Socket client = new Socket(host, port);   
      //建立连接后就可以往服务端写数据了  
      Writer writer = new OutputStreamWriter(client.getOutputStream(), "GBK");  
      writer.write("你好,服务端SSSSSSSSS");  
      writer.flush();  
      //写完以后进行读操作  
      BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(), "GBK"));  
      //设置超时间为10秒  
      client.setSoTimeout(3*1000);  
      StringBuffer sb = new StringBuffer();  
      String temp;  
      int index;  
      try {  
         while ((temp=br.readLine()) != null) {
//             if ((index = temp.indexOf("eof")) != -1) {  
//                 sb.append(temp.substring(0, index));  
//                 break;  
//             }  
            sb.append(temp);  
         } 
         System.out.println("服务端: " + sb.toString());
      } catch (SocketTimeoutException e) {     
       e.printStackTrace();
         System.out.println("数据读取超时。");  
      }          
     writer.close();  
      br.close();  
      client.close();  
     }  


}

main程序启动 ServerSocket服务端, 之后main程序启动客户端调用服务端,
现在是:服务端接收到 客户端的数据, 但是客户端无法接受服务端的数据,异常是请求超时。

服务端的
ServerSocket   kai shi
accept   kai shi
accept   kai shi
handleSocket!!!
客户端: 你好,服务端SSSSSSSSS


客户端的
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at com.zbxsoft.carbidbank.utils.Alltest.main(Alltest.java:93)
数据读取超时。

11 个解决方案

#1


java.io是流阻塞的。
将服务端的handleSocket方法修改一下可以看到效果。
		private void handleSocket() throws Exception {
System.out.println("handleSocket!!!");
// socket.setSoTimeout(2 * 1000);
BufferedReader br = new BufferedReader(new InputStreamReader(
socket.getInputStream(), "GBK"));
System.out.println("---->" + br.readLine());
System.out.println("---->" + br.readLine());
}

你会发现第一个readLine()执行之后就在等待,等到SoTimeout设置的时间到了,还没有读到数据所以第二个readLine()输入一个null.
回过头看一个原来的代码while ((temp=br.readLine()) != null) {,不难看出跳出while的时候正好就是timeout的时间。
一般在服务端将读和写分别用两个不同的线程处理互不影响

#2


引用 1 楼 bree06 的回复:
java.io是流阻塞的。
将服务端的handleSocket方法修改一下可以看到效果。
		private void handleSocket() throws Exception {
System.out.println("handleSocket!!!");
// socket.setSoTimeout(2 * 1000);
BufferedReader br = new BufferedReader(new InputStreamReader(
socket.getInputStream(), "GBK"));
System.out.println("---->" + br.readLine());
System.out.println("---->" + br.readLine());
}

你会发现第一个readLine()执行之后就在等待,等到SoTimeout设置的时间到了,还没有读到数据所以第二个readLine()输入一个null.
回过头看一个原来的代码while ((temp=br.readLine()) != null) {,不难看出跳出while的时候正好就是timeout的时间。
一般在服务端将读和写分别用两个不同的线程处理互不影响


那在实际开发中,都用什么办法呀, 是需要客户端和服务端 共同约定一个"end"字符吗? 客户端输出数据, 结尾加个"end"。
服务端接受数据时候,判断是否有end,跳出,再返回客户端吗,有没有例子呀,跪求提供

#3


那要看功能了,一般读和写分别线程。

说说需求。

#4


引用 3 楼 bree06 的回复:
那要看功能了,一般读和写分别线程。

说说需求。


我们服务器   给银行提供几个 socket服务接口, 他请求过来,我们给他返回数据
银行   也给我们提供几个 socket服务接口, 我们去请求,他再返回数据

你提到的socket服务端   读取  和 写入 分别用两个线程,大哥给我源码实例吧,我刚毕业。

另外,启动项目的时候, 这时候要启动socket服务 ,  也要用线程吧 。 
我开始写了个 serlvet 去启动socket服务, 完后 , 项目启动后就不往下走了,原因是在 server.accept();  堵塞了吧。
是不是启动项目的时候,也必须要用线程 启动socket服务。 通常是怎么做的呢

#5


客户端每次new 2个Socket  c1,c2,服务端每次accept  2次得到2个socket s1,s2,
c1 读<------>s1 写
c2 写<------>s2 读

如果一问一答方式,可以在一个线程里,如果可能出现不按顺序的问答,就需要把这两组放到两个线程里。

#6


如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

#7


怎么会在servlet(java web服务器)中启动socket服务呢?bs和cs同在?
你是不是理解错了?

#8


引用 6 楼 oh_Maxy 的回复:
如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

这种方式错的,请忽略。。。
应该只能一方发消息,一方接收消息,不能交替:c1先只写一句,s1只读一句,c1再写一句,s1再读一句.....

#9


引用 8 楼 oh_Maxy 的回复:
Quote: 引用 6 楼 oh_Maxy 的回复:

如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

这种方式错的,请忽略。。。
应该只能一方发消息,一方接收消息,不能交替:c1先只写一句,s1只读一句,c1再写一句,s1再读一句.....


恩恩,多谢多谢,还有一些问题, 过后我必须结贴给你分!

我是菜啊,问个问题, 我的项目是javaweb, 在启动项目的时候, 这个时候同时也应该开启ServerSocket吧,
 是不是大家一般都用ServletContextListener ,启动ServerSocket ?
启动ServerSocket 是不是大家都用多线程启动?  因为不多线程, 项目启动时候走到Socket.accept(); 就一直停止了。 
我没有任何经验, 麻烦前辈多说几句


#10


引用 9 楼 zc732888720 的回复:
Quote: 引用 8 楼 oh_Maxy 的回复:

Quote: 引用 6 楼 oh_Maxy 的回复:

如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

这种方式错的,请忽略。。。
应该只能一方发消息,一方接收消息,不能交替:c1先只写一句,s1只读一句,c1再写一句,s1再读一句.....


恩恩,多谢多谢,还有一些问题, 过后我必须结贴给你分!

我是菜啊,问个问题, 我的项目是javaweb, 在启动项目的时候, 这个时候同时也应该开启ServerSocket吧,
 是不是大家一般都用ServletContextListener ,启动ServerSocket ?
启动ServerSocket 是不是大家都用多线程启动?  因为不多线程, 项目启动时候走到Socket.accept(); 就一直停止了。 
我没有任何经验, 麻烦前辈多说几句



分给1L吧,他说的对哦~
Socket编程实际使用的比较少(应该是无..),你的思路应该是对的:
1. ServerSocket 创建好放到一个地方存着
2. 每accept到一个(如果有交互,可能要2个)socket就放到线程里,形成一个会话

可能出问题的地方有2个:
1. ServerSocket要保证在应用启动时创建好
2. 会话未完成前,保证线程不会中断

#11


你在4L说的两个线程分别读写,我这有个demo你可以看看:
服务端启动:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 服务端
 *
 */
public class SocketTest {
    public static void main(String[] args) {
        time();
    }

    public static void time() {
        long start = System.currentTimeMillis();
        // 专门负责向socket中写数据
        Socket writeSocket = null;
        // 专门负责从socket中读数据
        Socket readSocket = null;
        try {
            ServerSocket serverS = new ServerSocket(9000);
            System.out.println("---等待客户端连接---");
            // 服务端写操作对应客户端端读操作的socket
            writeSocket = serverS.accept();
            // 服务端读操作对应客户端读操作的socket
            readSocket = serverS.accept();
            System.out.println("---开始接收客户端消息---");

            // 读客户端信息
            FutureTask<Integer> readFuture = new FutureTask<Integer>(new ReadFromSocket(readSocket));
            new Thread(readFuture).start();
            // 写服务端信息
            FutureTask<Integer> writeFuture = new FutureTask<Integer>(new WriteToSocket(writeSocket, "Server"));
            new Thread(writeFuture).start();

            // 通过future的get操作,使线程处于持有状态,从而线程没有返回就不会结束
            if (0 == readFuture.get() && 0 == writeFuture.get()) {
                System.out.println("正常结束");
            } else {
                System.out.println("异常结束");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭各种资源的正确流程
            try {
                if (null != writeSocket) {
                    writeSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("总共连接时间:" + (end - start) + "(ms)");
    }

}

客户端启动:


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 客户端
 *
 */
public class ClientTest {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        start();
        long end = System.currentTimeMillis();
        System.out.println("总共连接时间:" + (end - start) + "(ms)");
    }

    public static void start() {
        // 专门负责从socket中读数据
        Socket readSocket = new Socket();
        // 专门负责向socket中写数据
        Socket writeSocket = new Socket();
        try {
            // 客户端读操作对应服务端写操作的socket
            readSocket.connect(new InetSocketAddress("127.0.0.1", 9000), 10000);// 连接不得超过10秒钟
            // 客户端写操作对应服务端读操作的socket
            writeSocket.connect(new InetSocketAddress("127.0.0.1", 9000), 10000);// 连接不得超过10秒钟
            // 读服务端信息
            FutureTask<Integer> readFuture = new FutureTask<Integer>(new ReadFromSocket(readSocket));
            new Thread(readFuture).start();
            // 写客户端信息
            FutureTask<Integer> writeFuture = new FutureTask<Integer>(new WriteToSocket(writeSocket, "Client"));
            new Thread(writeFuture).start();

            // 通过future的get操作,使线程处于持有状态,从而线程没有返回就不会结束
            if (0 == readFuture.get() && 0 == writeFuture.get()) {
                System.out.println("正常结束");
            } else {
                System.out.println("异常结束");
            }
        }// end try
        catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭各种资源的正确流程
            try {
                if (null != readSocket) {
                    readSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


读线程实现:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.concurrent.Callable;

public class ReadFromSocket implements Callable<Integer> {

    // 可用的Socket链接
    private Socket socket;

    public ReadFromSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public Integer call() throws Exception {
        // 合法性判断
        if (null == socket || !socket.isConnected()) {
            System.out.println("非法的Socket链接!");
            return -1;
        }
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while (!socket.isClosed() && socket.isConnected() && null != (line = br.readLine())) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Read---IO异常");
            e.printStackTrace();
            return -1;
        } finally {
            // 关闭各种资源的正确流程
            if (null != socket) {
                socket.close();
            }
            try {
                if (null != br) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

}


写线程:


import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Callable;

public class WriteToSocket implements Callable<Integer> {

    // 可用的Socket链接
    private Socket socket;

    // 角色
    private String role;

    public WriteToSocket(Socket socket, String role) {
        this.socket = socket;
        this.role = role;
    }

    @Override
    public Integer call() throws Exception {
        // 合法性判断
        if (null == socket || !socket.isConnected()) {
            System.out.println("非法的Socket链接!");
            return -1;
        }
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            Scanner sc = new Scanner(System.in);
            String tmp = null;
            for (; socket.isConnected() && !socket.isClosed();) {
                tmp = sc.nextLine();
                System.out.print("I say:" + tmp + System.getProperty("line.separator"));
                bw.write(role + " say:" + tmp);
                bw.newLine();
                bw.flush();
                if (tmp.endsWith("BYE")) {
                    break;
                }
            }
        } catch (IOException e) {
            System.out.println("Write---IO异常");
            e.printStackTrace();
            return -1;
        } finally {
            // 关闭各种资源的正确流程
            if (null != socket) {
                socket.close();
            }
            try {
                if (null != bw) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return 0;
    }
}

#1


java.io是流阻塞的。
将服务端的handleSocket方法修改一下可以看到效果。
		private void handleSocket() throws Exception {
System.out.println("handleSocket!!!");
// socket.setSoTimeout(2 * 1000);
BufferedReader br = new BufferedReader(new InputStreamReader(
socket.getInputStream(), "GBK"));
System.out.println("---->" + br.readLine());
System.out.println("---->" + br.readLine());
}

你会发现第一个readLine()执行之后就在等待,等到SoTimeout设置的时间到了,还没有读到数据所以第二个readLine()输入一个null.
回过头看一个原来的代码while ((temp=br.readLine()) != null) {,不难看出跳出while的时候正好就是timeout的时间。
一般在服务端将读和写分别用两个不同的线程处理互不影响

#2


引用 1 楼 bree06 的回复:
java.io是流阻塞的。
将服务端的handleSocket方法修改一下可以看到效果。
		private void handleSocket() throws Exception {
System.out.println("handleSocket!!!");
// socket.setSoTimeout(2 * 1000);
BufferedReader br = new BufferedReader(new InputStreamReader(
socket.getInputStream(), "GBK"));
System.out.println("---->" + br.readLine());
System.out.println("---->" + br.readLine());
}

你会发现第一个readLine()执行之后就在等待,等到SoTimeout设置的时间到了,还没有读到数据所以第二个readLine()输入一个null.
回过头看一个原来的代码while ((temp=br.readLine()) != null) {,不难看出跳出while的时候正好就是timeout的时间。
一般在服务端将读和写分别用两个不同的线程处理互不影响


那在实际开发中,都用什么办法呀, 是需要客户端和服务端 共同约定一个"end"字符吗? 客户端输出数据, 结尾加个"end"。
服务端接受数据时候,判断是否有end,跳出,再返回客户端吗,有没有例子呀,跪求提供

#3


那要看功能了,一般读和写分别线程。

说说需求。

#4


引用 3 楼 bree06 的回复:
那要看功能了,一般读和写分别线程。

说说需求。


我们服务器   给银行提供几个 socket服务接口, 他请求过来,我们给他返回数据
银行   也给我们提供几个 socket服务接口, 我们去请求,他再返回数据

你提到的socket服务端   读取  和 写入 分别用两个线程,大哥给我源码实例吧,我刚毕业。

另外,启动项目的时候, 这时候要启动socket服务 ,  也要用线程吧 。 
我开始写了个 serlvet 去启动socket服务, 完后 , 项目启动后就不往下走了,原因是在 server.accept();  堵塞了吧。
是不是启动项目的时候,也必须要用线程 启动socket服务。 通常是怎么做的呢

#5


客户端每次new 2个Socket  c1,c2,服务端每次accept  2次得到2个socket s1,s2,
c1 读<------>s1 写
c2 写<------>s2 读

如果一问一答方式,可以在一个线程里,如果可能出现不按顺序的问答,就需要把这两组放到两个线程里。

#6


如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

#7


怎么会在servlet(java web服务器)中启动socket服务呢?bs和cs同在?
你是不是理解错了?

#8


引用 6 楼 oh_Maxy 的回复:
如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

这种方式错的,请忽略。。。
应该只能一方发消息,一方接收消息,不能交替:c1先只写一句,s1只读一句,c1再写一句,s1再读一句.....

#9


引用 8 楼 oh_Maxy 的回复:
Quote: 引用 6 楼 oh_Maxy 的回复:

如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

这种方式错的,请忽略。。。
应该只能一方发消息,一方接收消息,不能交替:c1先只写一句,s1只读一句,c1再写一句,s1再读一句.....


恩恩,多谢多谢,还有一些问题, 过后我必须结贴给你分!

我是菜啊,问个问题, 我的项目是javaweb, 在启动项目的时候, 这个时候同时也应该开启ServerSocket吧,
 是不是大家一般都用ServletContextListener ,启动ServerSocket ?
启动ServerSocket 是不是大家都用多线程启动?  因为不多线程, 项目启动时候走到Socket.accept(); 就一直停止了。 
我没有任何经验, 麻烦前辈多说几句


#10


引用 9 楼 zc732888720 的回复:
Quote: 引用 8 楼 oh_Maxy 的回复:

Quote: 引用 6 楼 oh_Maxy 的回复:

如果一定要一组socket(c1,s1),就要严格遵循“一人一句”的方式:譬如c1先只一句,s1只读一句,s1再写一句,c1再读一句,完成一次会话。可以通过一些关键字判定是否继续这种问答方式。

这种方式错的,请忽略。。。
应该只能一方发消息,一方接收消息,不能交替:c1先只写一句,s1只读一句,c1再写一句,s1再读一句.....


恩恩,多谢多谢,还有一些问题, 过后我必须结贴给你分!

我是菜啊,问个问题, 我的项目是javaweb, 在启动项目的时候, 这个时候同时也应该开启ServerSocket吧,
 是不是大家一般都用ServletContextListener ,启动ServerSocket ?
启动ServerSocket 是不是大家都用多线程启动?  因为不多线程, 项目启动时候走到Socket.accept(); 就一直停止了。 
我没有任何经验, 麻烦前辈多说几句



分给1L吧,他说的对哦~
Socket编程实际使用的比较少(应该是无..),你的思路应该是对的:
1. ServerSocket 创建好放到一个地方存着
2. 每accept到一个(如果有交互,可能要2个)socket就放到线程里,形成一个会话

可能出问题的地方有2个:
1. ServerSocket要保证在应用启动时创建好
2. 会话未完成前,保证线程不会中断

#11


你在4L说的两个线程分别读写,我这有个demo你可以看看:
服务端启动:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 服务端
 *
 */
public class SocketTest {
    public static void main(String[] args) {
        time();
    }

    public static void time() {
        long start = System.currentTimeMillis();
        // 专门负责向socket中写数据
        Socket writeSocket = null;
        // 专门负责从socket中读数据
        Socket readSocket = null;
        try {
            ServerSocket serverS = new ServerSocket(9000);
            System.out.println("---等待客户端连接---");
            // 服务端写操作对应客户端端读操作的socket
            writeSocket = serverS.accept();
            // 服务端读操作对应客户端读操作的socket
            readSocket = serverS.accept();
            System.out.println("---开始接收客户端消息---");

            // 读客户端信息
            FutureTask<Integer> readFuture = new FutureTask<Integer>(new ReadFromSocket(readSocket));
            new Thread(readFuture).start();
            // 写服务端信息
            FutureTask<Integer> writeFuture = new FutureTask<Integer>(new WriteToSocket(writeSocket, "Server"));
            new Thread(writeFuture).start();

            // 通过future的get操作,使线程处于持有状态,从而线程没有返回就不会结束
            if (0 == readFuture.get() && 0 == writeFuture.get()) {
                System.out.println("正常结束");
            } else {
                System.out.println("异常结束");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭各种资源的正确流程
            try {
                if (null != writeSocket) {
                    writeSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("总共连接时间:" + (end - start) + "(ms)");
    }

}

客户端启动:


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 客户端
 *
 */
public class ClientTest {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        start();
        long end = System.currentTimeMillis();
        System.out.println("总共连接时间:" + (end - start) + "(ms)");
    }

    public static void start() {
        // 专门负责从socket中读数据
        Socket readSocket = new Socket();
        // 专门负责向socket中写数据
        Socket writeSocket = new Socket();
        try {
            // 客户端读操作对应服务端写操作的socket
            readSocket.connect(new InetSocketAddress("127.0.0.1", 9000), 10000);// 连接不得超过10秒钟
            // 客户端写操作对应服务端读操作的socket
            writeSocket.connect(new InetSocketAddress("127.0.0.1", 9000), 10000);// 连接不得超过10秒钟
            // 读服务端信息
            FutureTask<Integer> readFuture = new FutureTask<Integer>(new ReadFromSocket(readSocket));
            new Thread(readFuture).start();
            // 写客户端信息
            FutureTask<Integer> writeFuture = new FutureTask<Integer>(new WriteToSocket(writeSocket, "Client"));
            new Thread(writeFuture).start();

            // 通过future的get操作,使线程处于持有状态,从而线程没有返回就不会结束
            if (0 == readFuture.get() && 0 == writeFuture.get()) {
                System.out.println("正常结束");
            } else {
                System.out.println("异常结束");
            }
        }// end try
        catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭各种资源的正确流程
            try {
                if (null != readSocket) {
                    readSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


读线程实现:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.concurrent.Callable;

public class ReadFromSocket implements Callable<Integer> {

    // 可用的Socket链接
    private Socket socket;

    public ReadFromSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public Integer call() throws Exception {
        // 合法性判断
        if (null == socket || !socket.isConnected()) {
            System.out.println("非法的Socket链接!");
            return -1;
        }
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while (!socket.isClosed() && socket.isConnected() && null != (line = br.readLine())) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Read---IO异常");
            e.printStackTrace();
            return -1;
        } finally {
            // 关闭各种资源的正确流程
            if (null != socket) {
                socket.close();
            }
            try {
                if (null != br) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

}


写线程:


import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Callable;

public class WriteToSocket implements Callable<Integer> {

    // 可用的Socket链接
    private Socket socket;

    // 角色
    private String role;

    public WriteToSocket(Socket socket, String role) {
        this.socket = socket;
        this.role = role;
    }

    @Override
    public Integer call() throws Exception {
        // 合法性判断
        if (null == socket || !socket.isConnected()) {
            System.out.println("非法的Socket链接!");
            return -1;
        }
        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            Scanner sc = new Scanner(System.in);
            String tmp = null;
            for (; socket.isConnected() && !socket.isClosed();) {
                tmp = sc.nextLine();
                System.out.print("I say:" + tmp + System.getProperty("line.separator"));
                bw.write(role + " say:" + tmp);
                bw.newLine();
                bw.flush();
                if (tmp.endsWith("BYE")) {
                    break;
                }
            }
        } catch (IOException e) {
            System.out.println("Write---IO异常");
            e.printStackTrace();
            return -1;
        } finally {
            // 关闭各种资源的正确流程
            if (null != socket) {
                socket.close();
            }
            try {
                if (null != bw) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return 0;
    }
}