您的位置:首页 > 其它

理解socket的阻塞

2016-03-20 16:52 183 查看
    从socket中得到一个输入流InputStrean,然后从这个流中取数据,如果这个时候流里面的没有数据,可能是服务还没有发数据过来或发过来的数据也取完了,那么线程就会停在那里..直到服务器在发数据过来,从Socket的InputStream中取到了数据,这个线程才会向下走.所以当要和服务器交互通信的时候,就用一个while一真从Socket的流中数据取,流中的数据取完了就停在那里.等服务器在次发数据过来.---这就是阻塞的

    这个时候就有一个问题了,当我从Socket中的流中取数据时,如果服务器一直不发数据过来,也就是从Socket中得到的InputStream流中一直没有数据,那么这个程序就一直停在从流中取数据的那一行.

    如果过了很长时间服务器还没有数据发过来,就不等了,想让程序继续执行以后的代码.这时只一个办法,把服务器端关掉.客户端检测到这个Socket连接已断开,就不会停在从流中取数据的代码,而是执行下面的代码.

    显然以把服务器关掉的方式来让Socket连接断开有点不合适,所以我想到的办法就是用多线程.让线程A执行主代码,线程B去从流中读取数据,如果服务器又迟迟不发数据过来,又不关掉这个连接,那么线程B就一真让它阻塞在那里.

    上面的所有,用一包话来概括:javaIO流是阻塞流,(JavaNIO(java new io非阻塞流,NIO这里没有用到).

    这里在说说在ServerSocket是中的accept()方法也是一个阻塞方法,也就是如果没有客户端来连接,那么就线程就一直停在那里.直到有一个客户端口连接了,才开始执行后面的代码.

    从上面一点,可以看出如果要创建多客端的服务器,就要多次调用accept()方法,同要用多线程来做,线程A来一直循环执行accept().当有socket连接来过的时候就,创建一个新的线程来处理专门处理这个连接.

    到这里还没有完,因为前面提到过,Socket连接里面的输入输出流也是阻塞的,如果这个Socket连好过后,客户端和服务器迟迟不发数据,那么这个新创建的线程也会阻塞在那里,(除非这个新创建的线程里面不操作Socket里面的IO),为了阻止这种情况,就要像上面说的,在新创建的线程里面在新创建一个线程处理Socket里面的流的问题.

 

下面的程序的测试客户端口建议用Sockettool的一个小软件

public class SocketServer {

public static void main(String[] args) throws IOException {
ServerSocket serversocket = new ServerSocket(10088);
Socket socket = serversocket.accept();// 同样这也是一个阻塞方法
//当第一个客户端连接进来过后就会执行这句话,
System.out.println("accept方法通过了....");
//这个程序如果没有第二个客户端连进,那以下的代码不会执行到的.
Socket socket2 = serversocket.accept();
System.out.println("accept2方法通过了....");
InputStream instream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
String line="";
while (true){
line=reader.readLine();
if(line==null){
System.out.println("line 为NULL 了");
break;
}
System.out.println(line);
}
/**
* 程序有一种情况可以执行到这里,就是socket客户端口断开.不是socket2断开
* 第一个连接断开后line=reader.readLine();就不会在阻塞了.流中的数据读
* 完过后跳就跳出了while向下执行了.
*/
System.out.println("程序结束了");

// 关闭资源
socket.close();
serversocket.close();
}
}


所在要做网络编程就要到多线程.也这是多线程的一个理解:在多用户和多网络的的情况下,不可能为每一个用户,和网络请求都创建一个进程所以就有了线程.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: