在TCP协议中,如果发送端(客户端)关闭了,那么接收端(服务器端)端就会收到这个消息。

那么接收端(服务器端)怎么知道的呢?

我们进行实验:

首先在发送端中编写一段程序,当用户输入“end”的时候,关闭发送端。

import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class TCP_Send {
    public static void main(String[] args) throws Exception {
        //TCP使用的是Socket
        Socket s = new Socket("127.0.0.1",8989);

        OutputStream ops = s.getOutputStream();

        Scanner sc = new Scanner(System.in);
        while (true){
            String str = sc.next();
            if(str.equals("end"))
                break;
            ops.write(str.getBytes());
        }
        s.close();
    }
}

接收端(服务器端)与上一章最后所示一样。

重复代码
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCP_Receive {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(8989);

        Socket clinet = ss.accept();//会暂停,等待连接!

        InputStream input = clinet.getInputStream();

        byte[] buf = new byte[1024];
        while(true){
            int length = input.read(buf);
            System.out.println(new String(buf,0,length));
        }

//        clinet.close();
//        ss.close();
        //输入输出流,Socket会自动帮我们关闭
    }
}

然后分别运行接收端、发送端。

接收端(服务器端)报出上面异常。

于是我们开始分析错误的原因

根据提示提示最下面一行找到了错误(一般错误/异常最下面一行就是我们自己写的代码,上面的都是系统代码不会有错的)

System.out.println(new String(buf,0,length));

然后分析这一行的错误,我们往上一层查找。

发现错误原因是这一行代码

checkBoundsOffCount(offset, length, bytes.length);

 即:参数超出正常范围。

经过查找,我们发现length是-1,导致的错误。

也就是说,在我们编写的这行代码中,当流读取完了的时候,(发送端关闭的时候,这个流的生命也就走到尽头了

int length = input.read(buf);

返回值为-1

大家可以复习一下InputStream的知识

也就是说,我们可以将read返回值是否为-1作为发送端(用户端)是否关闭的信号

这就回答了文章开头所提的问题。

任务:当发送端关闭时,接收端也自动关闭

思路:增加一个判断,当length==-1时,跳出死循环,调用close()。又或者直接在while中判断即可

接收端(服务器端):

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCP_Receive {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(8989);
        Socket clinet = ss.accept();//会暂停,等待连接!
        InputStream input = clinet.getInputStream();
        byte[] buf = new byte[1024];

        int length = -1;
        while((length = input.read(buf))>=0){
            System.out.println(new String(buf,0,length));
        }

        clinet.close();
        ss.close();
        //输入输出流,Socket会自动帮我们关闭
    }
}

 

效果:

当输入end后,服务器端、客户端双双关闭

 

这就是TCP协议的好处

TCP协议中,接收端知道发送端什么时候关闭。

UDP协议中,接收端和发送端相互不知道对方的情况。