客户端服务端的socket连接后,服务端设置了SetSoTimeout,服务端在readLine阻塞中,过了Timeout时间,服务端的socket抛出异常,并且在抛出异常的catch中设置了服务端对应的socket.close()。这时问题来了。客户端服务端socket.close()时间后写数据量如DataOutputstream.write(str.getBytes()),DataOutputStream.flush().这两个客户端动作是否会抛出异常??

解决方案 »

  1.   

    你应该是TCP协议下吧,服务器端如果关闭socket,DataOutputstream.write(str.getBytes())肯定不行。你可以测试下。
      

  2.   

    是TCP协议。。
    我测试好像是没有抛出错误。。奇怪。
      

  3.   

    肯定是有问题了,那个时候服务端的socket已经关闭了,这个时候就已经关闭了连接,而此时客户端要写数据到网络流中是不行的,肯定会抛出异常了。
      

  4.   

    客户端:Socket socket = null;
    DataInputStream is = null;
    OutputStream os = null;
    try{
    socket = new Socket("127.0.0.1",iPort);
    socket.setSoTimeout(1000);
    is = new DataInputStream(socket.getInputStream());
    os = socket.getOutputStream();
    Thread.sleep(3000);
    os.write("000096789\n".getBytes());
    os.flush();
    }catch(IOException e){
    e.printStackTrace();
    }catch(InterruptedException e){
    e.printStackTrace();
    }finally{
    try{
    if (is != null) {
    is.close();
    is = null;
    }
    if (os != null) {
    os.close();
    os = null;
    }
    if (socket != null) {
    socket.close();
    socket = null;
    }
    }catch(Exception e){
    e.printStackTrace();
    }
    }
    服务端代码片段:

    try {
    socket.setSoTimeout(1000);
    is = new DataInputStream(socket.getInputStream());
    os = socket.getOutputStream();
            String str = is.readLine();
            System.out.println(length);
    }catch(Exception e){
        e..printStackTrace();
    }finally{
    try{
    if (is != null) {
    is.close();
    is = null;
    }
    if (os != null) {
    os.close();
    os = null;
    }
    if (socket != null) {
    socket.close();
    socket = null;
    }
    }catch(Exception e){
    e.printStackTrace();
    }
    }
    查看下有何问题
      

  5.   

    看我那个客户端代码和服务端代码。
    客户端sleep了3秒。服务端设置timeout为1秒。
    socket连接后服务端timeout了。但是客户端的    
    os.write("000096789\n".getBytes());
    os.flush();
    都能执行而不报异常。。什么原因呢?
      

  6.   

    ....
    你自己看清楚自己写的代码....
    1秒的时候已经抛异常了
    os.write("000096789\n".getBytes());
    os.flush();
    这两句根本就没有执行到...哪里再来的异常那....
      

  7.   

    你也太不负责任了。。
    Server端的异常并不会影响到这两句吧  ?  我测试了 这两句不会抛出异常。
      

  8.   

    我来 解惑 
    看下面代码    socket = new Socket("127.0.0.1",8899);
        socket.setSoTimeout(1000);
        is = new DataInputStream(socket.getInputStream());
        os = socket.getOutputStream();
        Thread.sleep(10000);     socket.setTcpNoDelay(true);
        FileOutputStream fo=new FileOutputStream("data.txt");
            DataOutputStream dos=new DataOutputStream(fo);
            dos.writeUTF(System.currentTimeMillis()+" Client Wakeup time");
             
        os.write("000096789\n".getBytes());
        os.flush();
        dos.writeUTF(System.currentTimeMillis()+" haha");
        while(socket.isClosed()){}
        dos.writeUTF(System.currentTimeMillis()+" client close time");
    上面是客户端下面是服务器端         if (socket != null) {
            
              
               FileOutputStream fo=new FileOutputStream("data1.txt");
               DataOutputStream dos=new DataOutputStream(fo);
               dos.writeUTF(System.currentTimeMillis()+"socket close Time\n");
               while(socket.isClosed()==false){}
               dos.writeUTF(System.currentTimeMillis()+"socket really close Time\n");
               
               
            }
    这是异常处理的代码   都打印到文件里
     
      

  9.   


    理论上我也认为是有异常呀。。但是就是不报异常的所以才求解不知道是不是和TCP协议有关。
      

  10.   

    结果是 结果是
    客户端调用write  和 flush方法并没有抛出异常。  再执行为这两个操作之后 ,客户端 socket 才关闭。
    服务器端 read 方法 由于超时阻塞以后 ,服务器端socket 被关闭, 如果在服务器端再调用 读写方法都会抛出异常  。 但是此时只是服务器端Socket 关闭,并向客户端 提出关闭请求。  客户端Socket 执行Write方法 并顺带确认关闭连接 。在执行完这次 write 后 Socket连接关闭。 如果再在客户端上调用 读写方法,则会抛出异常,你可以试一下。  这是 TCP 关闭时候也需要三次握手决定的。。  具体去看你的计算机网络吧   
      

  11.   


    TCP关闭连接的时候不是一端想关就可以关的,需要三次握手哦 你看一看
      

  12.   


    我很认同。。但是也是这样想。。再次想问的是,如何在发送write的时候捕捉到socket已经断开了呢?
      

  13.   


    服务器 端发送 关闭请求 并发送确认关闭祯。  然后自己单方面关闭socket,就是在 服务器端 调用close 方法的是时候 你在服务器端检测此时 socket状态 显示是关闭的,但在客户端却显示未关闭。
    当客户端收到服务器端的关闭Socket 请求后, 并不会立即关闭 本端Socket, 会先发送出本端就绪的数据,然后客户端会先把数据发完,然后关闭链接,并 发确认祯关闭链接
      

  14.   

    其实想要的结果是,知道服务端socket的关闭请求发过来后不发送出本端就绪的数据,直接关闭连接。并且后执行write且抛出异常。。求解。
      

  15.   

    哈 。。自习看了网络书 ,发现刚才说的不太严谨。TCP 连接可以被看做是两个方向的单工 连接组成。TCP连接的释放由两方分别关闭连接。 一方关闭连接后,意味着
    它不可以发数据但是还可以接收。TCP的释放是通过两方发送一个FIN 段被确认后那个方向的连接就关闭了,只有两个方向连接都关闭,TCP连接才释放。
    所以上面的过程是 ,服务器端申请关闭连接,并发送FIN, 客户端确认,然后服务器端关闭 。 客户端 先把数据发出后,也发FIN申请关闭,此时被 确认后,则SOCket 关闭。JAVA 对底层进行了包装,所以 close 方法的过程具体实现应该是。  一方申请关闭,并不再发送接受数据,
    另外一方将剩余数据发出,并关闭连接。  
      

  16.   

    因为 close 的实现看不到 ,所以只能猜测。  个人感觉 调用close后,就是宣布 就相当于调用了 shutDownInput 和 shutDownOutput   ,虽然 输入流可以过来,但是会被默默的 抛弃了。 所以你的问题不需要解决, 客户端发就是了,直接就被抛弃了。 但是当本端close 后再调用 读写方法就会抛出异常了。
      

  17.   

    如果 还有什么问题 可以加我好友一起讨论 我最近也在研究 NIO 和网络编程
      

  18.   

    在发出后加入判断语句 
    if(socket.isClosed){
    }
    如果发出后关闭了则说明发出失败。另外就是异步提示,比如 你发了这条后抛出异常 ,那么就提示上一条发送失败。
      

  19.   


    DataOutputstream.write(str.getBytes()),
    DataOutputStream.flush().
    这两句不会抛异常的,应为DataOutputstream用的是数据报(UDP协议)发送的,UDP协议的特点:只管发送,不管是否接收到,数据会丢失,发送完后立马关闭流通道,即断开连接,即使服务器端没有超时关闭,当客户端发送数据完了他也会关闭的。说以
    如果你用的是TCP协议的话,一定会抛出异常的,TCP特点:建立连接后就会一直开启流通道,不管有无通信,数据安全性高,不会丢失。如果流通道意外中断或是人为中断,建立流的两端都会抛出异常。
      

  20.   


    为什么说 这句是数据报协议?????  请问  TCP 建立的连接你是怎么用的数据报协议?
      

  21.   

    DataOutputstream.write(str.getBytes()),
    DataOutputStream.flush().
      
    你把DataOutputStream 当成DatagramSocket 了???
      

  22.   

    大神啊大神 快出现啊顺便去帮我解决一下NIO的疑问
      

  23.   

    有人说write之前可以先socket.sendUrgentData(0xFF);发送测试包。
    但是有些环境下,你发这个测试包服务端也认为你发的是正常数据。所以屏蔽这个做法。。有其他大神有解决方案么?
      

  24.   

    打打酱油
    try {
        socket.setSoTimeout(1000);
        is = new DataInputStream(socket.getInputStream());
        os = socket.getOutputStream();
            String str = is.readLine();
            System.out.println(length);
    }catch(Exception e){
        e..printStackTrace();
    }finally{
        try{
            if (is != null) {
                is.close();
                is = null;
            }
            if (os != null) {
                os.close();
                os = null;
            }
            if (socket != null) {
                socket.close();
                socket = null;
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
      

  25.   

    DataOutputstream.write(str.getBytes())会抛出异常。
    把客户端改一下:
    socket = new Socket("127.0.0.1", 1209); socket.setSoTimeout(1000);

    is = new DataInputStream(socket.getInputStream());
    os = socket.getOutputStream();
    while (true) {
    System.out.println("ok1");
    Thread.sleep(3000);
    os.write("000096789\n".getBytes());
    System.out.println("ok2");
    os.flush();

    }
      

  26.   


    你这个改了之后。其实write已经循环了2次了。第二次才报错的。
      

  27.   

    我也很诧异,明明Socket已经关闭了,居然还能读和写,并有任何异常抛出,求高手解答啊import java.io.*;
    import java.net.*;public class Server 
    {
    public static void main(String[] args) throws IOException
    {
    ServerSocket server = new ServerSocket(9999);
    Socket socket = server.accept();
    socket.close();
    }
    }
    import java.io.*;
    import java.net.*;public class Client
    {
    public static void main(String[] args) throws IOException
    {
    Socket socket = new Socket("127.0.0.1", 9999);
    InputStream in = socket.getInputStream();
    OutputStream out = socket.getOutputStream();

    try 
    {
    Thread.sleep(3000);
    }
    catch (InterruptedException e) 
    {
    e.printStackTrace();
    }

    int t = in.read();
    out.write(t);
    System.out.println(t);

    in.close();
    out.close();
    socket.close();
    }
    }
      

  28.   

    socket 的 write 是寫至系統的 buffer, 所以在對方 close socket 之後並不影響,
    通常 write 的異常是指寫至 buffer 有問題
      

  29.   


    数据报不是协议,是一种数据流。我想说的是数据报用的是UDP协议来传输的。
      

  30.   

    26楼说的很清楚了,服务器虽然关闭了流,但流资源并为被释放,所以你的在服务器端关闭流之前给客户端发消息通知。或者用if(socket.isClosed){}在客户端发送消息之前判断(TCP协议中这样是可以的,不知道UDP可不可以,你试试看)。
      

  31.   


    if(socket.isClosed){} 只能判断本地socket的。。所以无法实时判断对方是否断开的。。
      

  32.   

    没看你的代码,但可以肯定的是会抛异常
    因为服务器端socket关闭之后会将输入输出流都关闭, 这就意味着客户端soket持有的输入输出流也关闭了,
    此时再写数据,肯定会报异常.
      

  33.   


    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;public class Server {
    public static void main(String[] args) throws IOException {
    ServerSocket server = new ServerSocket(9999);

    Socket socket = server.accept();
    //在未有SOCKET client连接上来之前 close方法并未执行。
    socket.close();
    }
    }其实你客户端代码都不需要写,只要在浏览器里面输入:http://localhost:9999/
    服务端执行 accept 方法.然后socket就会断开!
      

  34.   

    server网线突然拔掉,socket.sendUrgentData(0)不起作用。write也不会异常,而且不管wirte多少次都不异常。netAddress.isReachable倒是可以在server突然断网的时候有效果,但是server断开立马连接到网络,又没有因为dhcp改变ip地址的话,就没用了。write函数竟然不是int返回值,这简直令人费解。
      

  35.   

    因为tcp协议判断断开与否是有一定时间的间隔的。但是楼上的情况我也很费解。。