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…

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

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

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

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

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

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

C++ 三种继承方式

C继承的一般语法为: class 派生类名:[继承方式] 基类名{派生类新增加的成员 };继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、private(私有的)和 protected&am…

java项目 异常如何解决_Java项目中常见的异常处理

发生异常的情况有很多,其中包括以下几大类:1. 空指针异常;2. 用户输入异常;3. 多层异常捕获;想要知道Java是如何处理异常的,就需要掌握以下这三种异常的处理:1.检查性异常:最具代表的…

java i/o 流详解_java I/O流详解

概况I/O流主要分为二大类别:字符流和字节流。字节流(基本流)1、字节输入流 类名:FileInputStream 特点:读(对文件进行读取操作) 父类:InputStream2、字节输出流 类名:FileOutputStream 特点:写…

C++ 向上转型

在 C 中经常会发生数据类型的转换,例如将 int 类型的数据赋值给 float 类型的变量时,编译器会先把 int 类型的数据转换为 float 类型再赋值;反过来,float 类型的数据在经过类型转换后也可以赋值给 int 类型的变量。 数据类型转换…

C++ 获取类型信息

typeid 运算符用来获取一个表达式的类型信息。类型信息对于编程语言非常重要,它描述了数据的各种属性: 对于基本类型(int、float 等C内置类型)的数据,类型信息所包含的内容比较简单,主要是指数据的类型。对…

C 数字排列组合

编辑程序让任意四个数字排列组合并且每一个排列组合的数字都不相同。 结果展示 完整代码 #include <stdio.h> //定义头文件 int main() {int i,j,k;printf("\n");for(i1;i<5;i){ //三重循环 for(j1;j<5;j){for(k1;k<5;k){ //确保 i j k 位置不同 i…

java 汇总_java基础汇总

1.关于Http和Hibernatet里面Session的区别HttpSessionHttpSession&#xff1a;是一个抽象接口&#xff0c;J2EE的Web程序在运行的时候&#xff0c;会给每一个新的访问者建立一个HttpSession&#xff0c;这个Session是用户身份的唯一标示&#xff0c;WEB 会话跟踪用的。【注:是容…

C 天数的计算

根据程序提示输入某年某月某日&#xff0c;判断这一天是这一年的第几天&#xff0c;并进行输出显示。 效果演示 完整代码 #include <stdio.h> int main() {int day,month,year,sum,leap;printf("\n请输入年、月、日&#xff0c;格式为&#xff1a;年,月,日&#…

java+filter加密_Javaweb之Filter案例练习-自动登录问题和MD5加密

自动登录问题和MD5加密前面已经完成了Filter的自动登录&#xff0c;但是有问题&#xff0c;我们在web.xml中Filter的url-mapping中配置的规则是/*, 也就是这个网站的所有请求都拦截。这肯定不合适。我们本来访问/login.jsp&#xff0c;本来就是去登录&#xff0c;结果也进行了拦…

C 从小到大排序

将数字按从小到大的的顺序进行排序输出&#xff0c;根据提示输入相应的数字个数&#xff0c;每输入一个数字要进行换行然后输入下一个数字&#xff0c;当三个数字完全输入之后点击回车&#xff0c;程序会根据从大到小的顺序进行数字的排序输出。 效果演示 完整代码 #include…

java class文件常量池_JAVA程序员谈谈class文件结构中的常量池-class文件

常量的类型有12种CONSTANT_Utf8_info1字面量UTF-8编码的字符串CONSTANT_Integer_info3字面量整型字面量CONSTANT_Float_info4字面量浮点型字面量CONSTANT_Long_info5字面量长整型字面量CONSTANT_Double_info6字面量双精度浮点型字面量CONSTANT_Class_info7符号引用类或接口的符…

C 输出图案

在C语言中使用 * 号输出各种图案。 用 * 输出字母C 效果 完整代码 #include <stdio.h>int main() {printf("用 * 号输出字母 C\n");printf(" ****\n");printf("*\n");printf("*\n");printf(" ****\n");} 用 * 输出…

C 多数排序

使用C语言编写程序对多个数字进行排序输出的操作。 根据提示输入十个数字并按照从小到大的顺序进行输出显示。 效果 完整代码 #include<stdio.h> #define N 10 int main() {int i,j,a[N],temp;printf("请输入 10 个数字&#xff1a;\n");for(i0;i<N;i)s…

java httppost wsdl_Java使用HttpUrlConnection调用webService(wsdl)

首先需要下载工具https://pan.baidu.com/s/1XQ-VubxcPFoqwGm7wierHg下载成功后解压打开exe程序&#xff0c;在wsdl endpoint中输入你wsdl的地址&#xff0c;点击get&#xff0c;等待一小会后会跳到invoke标签下的界面点击某个方法&#xff0c;例如上图的login&#xff0c;可以看…

C 反向输出

使用C语言的递归方法对输入的字符进行反向输出。 效果 完整代码 #include <stdio.h>int main() {int i5;void palin(int n);printf("请输入5个字符\40:\40");palin(i);printf("\n"); } void palin(n) int n; {char next;if(n<1) {nextgetchar(…

C 数组逆序输出

编写程序对固定内容的数组进行逆序输出&#xff0c;第一个值和最后一个值的位置互换。 效果 完整代码 #include<stdio.h> #define N 10 int main() {int a[N]{10,100,20,43,54,15,6,77,82,91};int i,t;printf("原始数组是:\n");for(i0;i<N;i)printf(&quo…