Socket通讯产生阻塞的解决方案
来源:互联网 发布:中国旅游数据统计 编辑:程序博客网 时间:2024/06/06 18:05
Socket通讯正常想实现的流程:
是客户端给服务端发送发送报文,当服务端接收到报文后,给客户端一个反馈信息。
目前代码实现情况是:
客户端和服务端在read时都被阻塞了,经过反复的查阅相关资料和测试,发现了问题的根本。
导致read阻塞的原因是:
当客户端给服务端发送完数据的时候服务端在读取数据,但是服务端没有办法判断什么时候会自动中断,所以服务端会在这个地方阻塞。
阻塞之后服务端就没有办法往客户端发送数据,这个时候客户端的接收数据也会等服务端的数据,会在这里阻塞。这个时候服务端和客户端都不会关闭,会一直持续阻塞。客户端传递数据的时候,服务端不知道什么时候终止,用read!=-1是没有办法判断出来的,因为客户端流没有终止,流一直存在,所以服务端以为数据没有传输完毕。
有两个解决方案,方案如下:
1.在客户端传输结束之后,你可以把流进行关闭,使用socket.shutdownOutput()和socket.shutdownInput()这两个方法,将流关闭掉,对面就可以接收到结束的信号。
2.双方约定好,定义一个结束符,客户端每次给服务端发送报文时,在发送结束加上结束符;当服务端这面接收到报文读取时,读到结束符的话,就证明是结束了,就不在循环了。
方案1服务端代码:
package com.pactera.ok;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; /** * @Title:TestZLFServer * @Description: * @company:XXXXXX * @author:XXXXXX-zhanglf * @date:2017-5-16 * @version:1.0.0 */public class TestZLFServer { public static void main(String[] args) { try { ServerSocket ss=new ServerSocket(10086); Socket s=ss.accept(); InputStream is=s.getInputStream(); BufferedReader br=new BufferedReader(new InputStreamReader(is)); OutputStream os=s.getOutputStream(); PrintWriter pw=new PrintWriter(os); //读取用户输入信息 String info=null; while(((info=br.readLine()) !=null)){ System.out.println("我是服务器,用户信息为:"+info); s.shutdownInput(); } //给客户端一个响应 String result="客户端,我收到你发过的信息了,通知你一下"; pw.write(result); pw.flush(); pw.close(); os.close(); br.close(); is.close(); s.close(); ss.close(); } catch (IOException e) { e.printStackTrace(); } } }
方案1客户端代码:
package com.pactera.ok;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetAddress;import java.net.Socket; import java.net.UnknownHostException; /** * @Title:TestZLFClient * @Description: * @company:XXXXXX * @author:XXXXXX-zhanglf * @date:2017-5-16 * @version:1.0.0 */public class TestZLFClient { public static void main(String[] args) { try { Socket s =new Socket(InetAddress.getLocalHost(),10086); OutputStream os=s.getOutputStream(); PrintWriter pw=new PrintWriter(os); InputStream is=s.getInputStream(); BufferedReader br=new BufferedReader(new InputStreamReader(is)); //给服务端发送的短信内容 String info="ssssssssssss"; pw.write(info); pw.flush(); s.shutdownOutput(); //不加这句代码,客户端输出不了给果: //接收服务器的相应 String result=null; while(!((result=br.readLine())==null)){ System.out.println("接收服务器的信息:"+result); } //关闭资源 br.close(); is.close(); pw.close(); os.close(); s.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
方案2服务端代码:
package com.pactera.ok3;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/** * @Title:Server3 * @Description: * @company:XXXXX * @author:XXXXX-zhanglf * @date:2017-5-16 * @version:1.0.0 */public class Server3 {public static void main(String[] args) { try { // 创建一个服务端ServerSocket,监听指定端口的请求 ServerSocket ss = new ServerSocket(10086); System.out.println("=============Server 等待客户端接入==============="); // 监听客户端请求 Socket socket = ss.accept(); // 与客户端建立连接之后,读取客户端发过来的信息 InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; // 定义一个字符串构建器,用于存储客户端发过来的数据 StringBuilder sb = new StringBuilder(); int index; while ( (len=is.read(buffer)) != -1 ) {String temp = "";String tmp = new String(buffer, 0, 2); /**01-单独给信贷系统增加的处理逻辑**/if("xd".equals(tmp)){temp = new String(buffer, 0, len); //System.out.println("temp ====== : "+temp);// 读到结束符,则跳出循环 if ( (index=temp.indexOf("eof")) != -1 ) { // 截取指定长度 sb.append(temp.substring(2, index)); break; } }else{/**02-核心原有处理逻辑**/temp = new String(buffer, 0, len); }// 如果没有读到结束符,则继续读取,并加入字符串构建器 sb.append(temp); } System.out.println("Server 来自客户端的信息 : " + sb.toString()); // 读完之后,往客户端发送响应数据 OutputStream out = socket.getOutputStream(); out.write("Hello Client!".getBytes()); out.write("eof".getBytes());// 写一个结束符 out.flush(); out.close(); is.close(); socket.close(); ss.close();}catch (Exception e) {e.printStackTrace(); }}}
方案2客户端代码:
package com.pactera.ok3;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;/** * @Title:Client3 * @Description: * @company:XXXXX * @author:XXXXX-zhanglf * @date:2017-5-16 * @version:1.0.0 */public class Client3 {public static void main(String[] args) { try{// 与服务端建立连接(服务端主机号,服务端监听的端口号) Socket socket = new Socket(InetAddress.getLocalHost(),10086); // 与服务端建立连接之后,就可以往服务端写数据 OutputStream out = socket.getOutputStream(); // 往服务端中写数据 out.write("xd|0|001101|150XXXXXXXX|您好,你卡号取款200元。|".getBytes()); out.write("eof".getBytes());// 写一个结束符,表示写入完毕 out.flush(); // 写完之后,获取服务端的响应数据 InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; // 定义一个StringBuilder存储客户端发过来的数据 StringBuilder sb = new StringBuilder(); int index; while ( (len=is.read(buffer)) != -1 ) { String temp = new String(buffer, 0, len); // 读到结束符,则跳出循环 if ( (index=temp.indexOf("eof")) != -1) { sb.append(temp.substring(0, index)); break; } sb.append(temp); } System.out.println("Client 来自服务端的信息 : " + sb.toString()); out.close(); is.close(); socket.close();}catch (Exception e) {e.printStackTrace();}}}
阅读全文
1 0
- Socket通讯产生阻塞的解决方案
- 读Socket流时产生阻塞的解决方案
- 读Socket流时产生阻塞的解决方案
- Socket通讯读取数据阻塞解决方案
- socket通讯输入流输出流阻塞解决方案
- 非阻塞socket通讯(select函数的使用)
- android Socket通讯时readline阻塞
- linux read socket时产生阻塞
- Socket的阻塞/非阻塞
- Socket的阻塞/非阻塞
- Socket的阻塞/非阻塞
- Socket的阻塞/非阻塞
- Socket的阻塞/非阻塞
- Socket的阻塞/非阻塞
- Socket的阻塞/非阻塞
- Visual Basic Winsock API操作模块(基于API方式的socket同步阻塞通讯类)
- 安卓开发SOCKET编程中几种线程阻塞产生的原因与解决办法
- oracle锁与死锁概念,阻塞产生的原因以及解决方案
- AppServ安装并配置好MySQL环境,并用phpMyAdmin登录MySQL
- oracle 各种字段的类型的定义
- centos7.3安装openstack-mitaka
- caffe架构分析
- 关于Cocos2d-x中定时器的使用总结
- Socket通讯产生阻塞的解决方案
- Makefile经典教程(掌握这些足够)
- 加息预期在前挡路 难道黄金就真的不敢涨了吗?
- RxJava 与 Retrofit 结合的最佳实践
- 启动tomcat不用安装jdk
- 关于STM32F4的AHB和APB时钟频率的问题
- intelliJ idea2016将web工程打成war包解决方案
- 解决Fragment偶发异常java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
- MFC控件的用法