Socket编程 之 一种死锁现象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MakeContral/article/details/78234315

刚接触socket编程的过程中,很容易出现死锁的现象。下面我来介绍一种死锁的原因和解决的方法。

先来看这段代码:

/*客户端发送一个信息到服务端*/
 Socket socket = new Socket("127.0.0.1", 8081);
 outputStream = socket.getOutputStream();
 outputStream.write("服务器我想要一个html文件".getBytes());

/*接受服务器传来的响应信息*/
 inputStreams = socket.getInputStream();
 byte[] bytes = new byte[1024];
 StringBuilder stringBuilder = new StringBuilder();
 int len = 0;
 while((len = inputStreams.read(bytes))!=-1){
     stringBuilder.append(new String(bytes,0,len));
 }

代码很简单。就是先往服务器发送一个信息,然后服务器解析完信息后,传回一个响应的内容。然后客户端再接受该响应。

再来看服务器端的代码:

 ServerSocket serverSocket = new ServerSocket(8081, 1, InetAddress.getByName("127.0.0.1"));
 /*接受客户端的socket,若没有连接,会一直阻塞到有连接进来*/
 Socket socket = serverSocket.accept();

 /*服务器解析客户端传来的信息*/
 inputStream = socket.getInputStream();
 StringBuilder sb = new StringBuilder();
 byte[] bytes = new byte[1024];
 int len = 0;
 while((len=inputStream.read(bytes))!=-1){
    sb.append(new String(bytes,0,len));
 }

 /*服务器解析完传来的信息后,做出响应*/
 outputStream = socket.getOutputStream();
 outputStream.write("html文件来了".getBytes());

1.假设服务器的线程先与客户端运行。ServerSocket被执行到,然后调用accept();处于阻塞,一直等到一个socket进来。

2.与此同时客户端生成了一个socket并且传来了一个信息“服务器我想要一个html文件”。writer被执行后会继续执行到inputStreams.read(),因为read是阻塞的会一直等到服务端把响应信息传回。所以出于阻塞中。

3.accept()接受到socket之后就会去解析客户端传来的信息了,执行到inputStream.read()的时候,也会被阻塞。有人问客户端不是传来了“服务器我想要一个html文件”的信息了吗?为什么read还会被阻塞啊。这是因为read还没有读到-1。

服务器没有读到-1,会以为还有信息要传来,于是也处于等到中。可是客户端已经传输好了,并且在等服务器给响应信息呢。于是就发生了死锁。

解决的办法有两种:

第一种方法close流,相当于给流中加入一个结束标记-1
第二种方法:s.shutdownOutput();//关闭客户端的输出流。

相当于给流中加入一个结束标记-1.这个样子服务器的输入流的reaLine方法就会读到一个-1,然后结束readLIne方法。也可以这样理解s.shutdownOutput();关闭的是客户端的输出流,同时服务器端的输入流也随之关闭。s.shutdownIntput();也是同样的道理,关闭客户端的输入流,同时服务器端的输出流也随之关闭。

通过socket.shutdownOutput()关闭输出流,但socket仍然是连接状态,连接并未关闭
如果直接关闭输入或者输出流,即:in.close()或者out.close(),会直接关闭socket

猜你喜欢

转载自blog.csdn.net/MakeContral/article/details/78234315
今日推荐