[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[整理]Java如何判断单次输入流结束?

上一篇:[整理]给下拉框的每一项追加提示文字 Setting a Tool Tip for an Item in a JList Component
下一篇:[转帖]Java中使用TelnetClient的一个范例

添加日期:2011/1/26 10:04:54 快速返回   返回列表 阅读9529次
--------------------------------------------
流结束,并不代表连接结束,如果只传送一次,你关掉可以,如果是持续性的,你还能关掉Socket吗?,
例如批量发送文件,发送开始的时间,最好设置一个标志位,一个文件发送结束的时间,改变这个标志位,
接收方根据标志位,来决定是继续接收,还是接收完毕,开始接收下一个文件. 
-------------------------------------
不明白版主说的Socket是长连接是什么意思.
Java当中的Socket类,其实是使用TCP协议进行传输的.TCP是可靠的一种传输协议.

如果版主想用TCP协议,并且,服务端和客户端,在没有信息进行传输的时候,也不断开连接,一般情况下,客户端会在Socket超时之前,想服务端发送一个用于维持连接的信息包,来维持连接.但是TCP协议,并不是指长连接.我们每天上网浏览网页,其实,也是以TCP协议为基本的传输协议的.只是,这个是短连接的形式,每次浏览器向服务器提交一个请求,服务短应答请求,然后断开连接.

在应用TCP协议,并且是长连接传输信息的情况下.通常会再封装一层协议的.但,观察版主的收发内容,并没有涉及这一层,所以,我这里并不知道是长连接.

首先,我们要明确一点,发送方如果不将输出流进行关闭,接收方就会认为输入流没有结束,直到超时.
其次,我们判断一个信息是否已经完全的读取完毕,除了使用输入流结束这种办法,还可以自行封装一层协议,用于信息的交互.
当然,我们也可以采用Http那样的交互方式进行信息的传递,但是,它是短连接的.

下面我来说一下,TCP长连接传输数据的一般做法.
一般情况下,我们会在TCP的基础上再封装一层协议,用户长连接的传输.协议的信息包,也分包头和包体两个部分.
包体,主要就是我们要传输的信息.(维持连接的信息包,包体可为空)
包头,一般分为三个部分.第一部分是信息包的长度(长度一般是指整个信息包的长度);第二部分是包体信息的类型(在这里指出是否是维持连接包);第三部分是信息包的序列号,一般情况下,这个序列号要确保在传输过程中唯一标识该信息包.
如果为了安全起见,还可以在包体后添加包尾,包尾数据用于对包体数据的验证)

这样,通信双方就可以根据包长来判断一次接收的操作是否结束了.
-----------------------------------


//---------------------------输入流读取线程-----------------------------
class printInputThread extends Thread {
    public void run() {
        
        //只有该线程读取该流.
        InputStream in = CommandExecutor.in;
        StringBuilder inputStr = new StringBuilder();
        char ch;

        try {
            while (!isInterrupted()) {
                //可读取的字节数
                int canReadCount = in.available();
                System.out.println("read available:"+canReadCount);
                if(canReadCount>0){
                    for(int i=0;i<canReadCount;i++){
                        inputStr.append((char)in.read());
                    }
                    // 追加到结果区域
                    System.out.println("read available:"+inputStr.toString());
                    Start.mainFrame.appendResultText(inputStr.toString());
                    inputStr.delete(0, inputStr.length());
                }
                //读取一个字节,无数据则阻塞
                ch = (char)in.read();
                inputStr.append(ch);
                System.out.println("read one:"+ch);
            }
        
        } catch (IOException e) {
            //执行exit命令时,连接会被断开,报SocketException:Connection reset
            //点“断开连接”按钮,中断该线程时,执行in.read()时,有可能流已经被关闭,报socket closed
            //点“断开连接”按钮,中断该线程时,in.read()方法被中断时,抛出InterruptedIOException异常
            //如果正在执行in.available(),而流已经被关闭,报java.io.IOException: Stream closed
            //不能保证该线程的中断会在tc.disconnect()之前执行,即不能保证它在流关闭前被中断。
            
            //干脆,SocketException也不抓了,也不详细区分异常类型,一律作为断开连接处理。
            
            //断开tc的连接,切换界面状态
            Start.mainFrame.disconnect();

            //输出LOG以备查看
            e.printStackTrace();
        }
        
        System.out.println("printInputThread ended.");
    }
}


这是我写的一段代码,问题是无法知道执行单次命令的返回信息在哪里结束。

一次的返回信息,in.read()可能要阻塞一两次才能完全读完。

它阻塞了,也不能代表这次数据就读完了。

头疼……

还是得找个返回信息结束标识字符才行……
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved