java socket 阻塞模式_Java中Socket Read阻塞问题

本人来说并不熟悉JAVA语言,只是近期在分析某个简单的java agent程序时,根据对应的代码写了一个对接的程序,两者之间是典型的C/S socket编程。客户端在向服务端发送相应的指令后,服务端(装agent的主机)执行后会返回执行的数据给客户端。在直接一行行收取数据时是正常的,但通过while循环时会卡住。

一、java读取数据的两种方式

从Socket上读取对端发过来的数据一般有两种方法:一种是按字节,一种是按字符。

1、按照字节流读取

BufferedInputStream in = new BufferedInputStream(socket.getInputStream());

int r = -1;

List l = new LinkedList();

while ((r = in.read()) != -1) {

l.add(Byte.valueOf((byte) r));

}

2、按照字符流读取

readLine()方法在进行读取一行时,只有遇到回车(\r)或者换行符(\n)才会返回读取结果,这就是“读取一行的意思”。如果不指定buffer大小,则readLine()使用的buffer有8192个字符。在达到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才会返回。BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

String s;

while ((s = in.readLine()) != null) {

System.out.println("Reveived: " + s);

}

read()和readLine()都会读取对端发送过来的数据,如果不加while循环时,是不会存在异常阻塞的情况的。但在使用while后,如果无数据可读,就会阻塞直到有数据可读。或者到达流的末尾,这个时候分别返回-1和null。具体也可以参看segmentfault上别人的提问和回答。

使用while的好处就是对于返回数据较多的情况,比较方便,如果是直接readLine而不加while时,默认只能取得最后一行的数据;其坏处也显而易见----阻塞等待。

二、异常处理

1、服务端处理

发送完后调用Socket的shutdownOutput()方法关闭输出流,这样对端的输入流上的read操作就会返回-1。注意不能调用socket.getInputStream().close()。这样会导致socket被关闭。当然如果不需要继续在socket上进行读操作,也可以直接关闭socket。但是这个方法不能用于通信双方需要多次交互的情况。

2、客户端处理

为了防止read操作造成程序永久挂起,还可以给socket设置超时。例如下面的方法设定超时3秒:

socket.setSoTimeout(3000)

如果read()方法在设置时间内没有读取到数据,就会抛出一个java.net.SocketTimeoutException异常。

3、双方约定

发送数据时,约定数据的首部固定字节数为数据长度。这样读取到这个长度的数据后,就不继续调用read方法。或者双方约定结尾字符信息,在读取到相应信息时,客户端主动发送断开连接的信息,或者发送信号给服务端,由服务端断开连接。

三、其他

我在实际使用中,使用了上面异常处理中提到的第三种。但在应用中如果由客户端进行超进异常断开连接时,客户端在接收数据过程中会收到异常信息如下:

679f8908489e8334b52749d70545ebc8.png

这时候就需要使用try……catch(Exception e)语句进行异常捕获处理。最终一个完整的客户端请求如下:

import java.io.*;

import java.net.*;

public class TalkClient {

public static void main(String args[]) {

try{

Socket socket=new Socket("127.0.0.1",4700);

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

BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));

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

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

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

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

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

String readline;

readline=sin.readLine(); //从系统标准输入读入一字符串

while(!readline.equals("bye")){

//若从标准输入读入的字符串为 "bye"则停止循环

os.println(readline);

//将从系统标准输入读入的字符串输出到Server

os.flush();

//刷新输出流,使Server马上收到该字符串

System.out.println("Client:"+readline);

//在系统标准输出上打印读入的字符串

System.out.println("Server:"+is.readLine());

//从Server读入一字符串,并打印到标准输出上

readline=sin.readLine(); //从系统标准输入读入一字符串

} //继续循环

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

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

socket.close(); //关闭Socket

}catch(Exception e) {

System.out.println("Error"+e); //出错,则打印出错信息

}

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/564272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 窗体 源码_Java制作MDI窗体源代码

由于实际需要做一个MDI窗体,百度里面找到一个不错的源代码给大家分享一下。import javax.swing.*;import java.awt.event.*;import java.awt.*;class JInternalFrame1 extends JFrame implements ActionListener{JDesktopPane desktopPane;int count 1;public JInt…

MySQL 创建触发器

触发器是与 MySQL 数据表有关的数据库对象&#xff0c;在满足定义条件时触发&#xff0c;并执行触发器中定义的语句集合。 基本语法 在 MySQL 5.7 中&#xff0c;可以使用 CREATE TRIGGER 语句创建触发器。 语法格式如下&#xff1a; CREATE <触发器名> < BEFORE …

java通过url获取网页内容_Java语言通过URL读取网页数据并保存到本地文件(代码实例)...

本文主要向大家介绍了Java语言通过URL读取网页数据并保存到本地文件(代码实例)&#xff0c;通过具体的内容向大家展示&#xff0c;希望对大家学习JAVA语言有所帮助。Java通过URL读取网页数据并保存到本地文件(代码实例)import java.io.*;import java.net.MalformedURLException…

MySQL 修改和删除触发器

修改触发器可以通过删除原触发器&#xff0c;再以相同的名称创建新的触发器。 基本语法 与其他 MySQL 数据库对象一样&#xff0c;可以使用 DROP 语句将触发器从数据库中删除。 语法格式如下&#xff1a; DROP TRIGGER [ IF EXISTS ] [数据库名] <触发器名>语法说明如…

java做主成分分析_主成分分析(PCA) Java

导入jar包:Jama-1.0.2.jar//计算类import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Map.Entry;import java.util.TreeMap;import Jama.Matrix;/**…

idl文件生成java_IDL和生成代码分析

IDL:接口描述语言这里使用thrift-0.8.0-xsb这个版本来介绍IDL的定义以及简单实例分析。1. namespace 定义包名2.struct 结构体&#xff0c;定义服务接口的参数和返回值用到的类结构。基本类型不需要使用struct.3.service 定义接口&#xff1a;demo.thrift1 namespace java com.…

java从控制台读取数据_Java不同版本从控制台读取数据方法及优缺点分析

从JDK 5.0版本开始&#xff0c;能从控制台中输入数据的方法每增加一个版本号&#xff0c;就有一种新增的方法&#xff0c;这也增加了选择的种类&#xff0c;可以依据不同的要求来进行选择。下面和绿茶小编一起来了解一下各个版本从控制台中读取数据的方法以及各自的优缺点。1、…

java类和对象程序_Java类与对象程序设计基础

Java类与对象程序设计基础一、实验目的&#xff1a;通过编制一个独立应用程序&#xff0c;使得学生掌握Java的系统所提供类的引用方法&#xff1b;通过编制一个完整的应用程序&#xff0c;使得学生对Java的应用程序的基本构成和基本算法熟练掌握&#xff0c;同时熟悉Java开发环…

MySQL 修改和删除索引

MySQL 中修改索引可以通过删除原索引&#xff0c;再根据需要创建一个同名的索引&#xff0c;从而实现修改索引的操作。 基本语法 当不再需要索引时&#xff0c;可以使用 DROP INDEX 语句或 ALTER TABLE 语句来对索引进行删除。 1 使用 DROP INDEX 语句 语法格式&#xff1a;…

java记事本保存_JAVA记事本关于保存

为什么运行这个程序后点击保存&#xff0c;然后打开时不是按行输出的啊?哪里有问题&#xff1f;publicclassJSBJSB{publicstaticvoidmain(String[]args){FirstWindowwinnewFirstWindow("记事本");}}classF...为什么运行这个程序后点击保存&#xff0c;然后打开时不是…

MySQL 创建用户

在对 MySQL 的日常管理和实际操作中&#xff0c;为了避免用户恶意冒名使用 root 账号控制数据库&#xff0c;通常需要创建一系列具备适当权限的账号&#xff0c;应该尽可能地不用或少用 root 账号登录系统&#xff0c;以此来确保数据的安全访问。 创建用户 可以使用 CREATE U…

acm用java怎么写_用java来写ACM

前言从去年10月份开始就一直都在九度oj平台写acm&#xff0c;到今天在九度oj的总排名已经到了第6名&#xff0c;收获很多特别是算法和数据结构方面的提高&#xff0c;这种提高直接反映在我找工作的顺利中但是人总要学会拥抱变化&#xff0c;特别是我即将加入阿里系&#xff0c;…

MySQL 修改用户

修改用户账号 可以使用 RENAME USER 语句修改一个或多个已经存在的 MySQL 用户账号。 语法格式&#xff1a; RENAME USER <旧用户> TO <新用户>语法说明如下&#xff1a; <旧用户>&#xff1a;系统中已经存在的 MySQL 用户账号。<新用户>&#xff1…

MySQL 删除用户

MySQL 数据库中可以使用 DROP USER 语句来删除一个或多个用户账号以及相关的权限。 语法格式&#xff1a; DROP USER <用户名1> [ , <用户名2> ]…使用 DROP USER 语句应该注意以下几点&#xff1a; DROP USER 语句可用于删除一个或多个 MySQL 账户&#xff0c;并…

python模块使用相对路径还是绝对路径、哪种更好_python学习的第十八天模块之包、相对搜索路径和绝对搜索路径...

一、包1、什么是包包是一种通过使用‘.模块名’来组织python模块名称空间的方式。具体就是一个包含有__init__.py文件的文件夹&#xff0c;所以其实我们创建包的目的就是为了用文件夹将文件/模块组织起来PS&#xff1a;(1)在pyhton3中没有__init__不会报错&#xff0c;但在pyth…

python的pygame库使用方法_[宜配屋]听图阁

使用python pygame库实现一个双人弹球小游戏&#xff0c;两人分别控制一个左右移动的挡板用来拦截小球&#xff0c;小球会在两板间不停弹跳&#xff0c;拦截失败的一方输掉游戏&#xff0c;规则类似于简化版的乒乓球。因为是第一次用pygame写python小游戏并且只用了两三个小时&…

MySQL 删除用户权限

MySQL 数据库中可以使用 REVOKE 语句删除一个用户的权限&#xff0c;此用户不会被删除。 语法格式有两种形式&#xff0c;如下所示&#xff1a; 1 第一种&#xff1a; REVOKE <权限类型> [ ( <列名> ) ] [ , <权限类型> [ ( <列名> ) ] ]… ON <对…

java jdbc 多数据源_Jdbctemplate多数据源配置方法详解

1.数据源配置spring:# jdbctemplate 连接多数据源配置db1:datasource:jdbcurl: jdbc:mysql://127.0.0.1:3306/cloud-main1?useUnicodetrue&characterEncodingutf8&useSSLfalse&allowMultiQueriestrueusername: rootpassword: 123456driver-class-name: com.mysql.…

java 语法 泛型_java-解密泛型语法

我正在阅读一个问题,下面给出了方法的签名public static List super E> doIt(List nums)我无法解码语法.我对仿制药很陌生,无法理解这部分.第一部分< E扩展了CharSequence>都告诉E应该是什么作为参数和返回类型.但我确实看到列表了吗&#xff1f;超级E&gt ;,这定义…

MySQL 数据库恢复

数据库恢复是指以备份为基础&#xff0c;与备份相对应的系统维护和管理操作。 系统进行恢复操作时&#xff0c;先执行一些系统安全性的检查&#xff0c;包括检查所要恢复的数据库是否存在、数据库是否变化及数据库文件是否兼容等&#xff0c;然后根据所采用的数据库备份类型采…