查看read如下:
public abstract int read(char[] cbuf, int off, int len) throws IOException将字符读入数组的某一部分。在某个输入可用、发生 I/O 错误或者到达流的末尾前,此方法一直阻塞。
下面上传图片的代码,张孝祥老师说服务器端无法识别结束标示,这个无法识别应该是某个输入可用。因为通过 sk.shutdownOutput () 就可以禁用此套接字的输出流,而客户端的输出流正好对应服务器端的输入流的。因为如果不用sk.shutdownOutput()的话,就表示客户端在使用着输出流,所以服务器端的read()方法一直处于阻塞。
import java.net.*;
import java.io.*;
class TCPClient{
public static void main(String[] args) throws Exception{
Socket sk =new Socket();
//通过connect方法连接
sk.connect(new InetSocketAddress(InetAddress.getByName("192.168.1.100"),10009));
//为了发送数据需要获得Socket流的输出流
FileInputStream fis=new FileInputStream("1.gif");
OutputStream ops=sk.getOutputStream();
byte[] buf=new byte[1024];
int len;
while((len=fis.read(buf))!=-1){
ops.write(buf, 0, len);
}
sk.shutdownOutput();
InputStream ips=sk.getInputStream();
byte[] bufr =new byte[1024];
ips.read(bufr);
String ref=new String(bufr,0,bufr.length);
System.out.println(ref);
fis.close();
sk.close();
}}
/*
需求:定义端点接受数据并打印在控制台上
1.通过ServerSocket建立服务端Socket
2.获得客户端的对象。通过accept方法实现,这个方法是阻塞式的,没有连接就会等。
3,客户端如果发送过来数据,服务端需要用对于的客户端对象,用客户端对象会的输入流对象,并打印到控制台
4.关闭服务(可选操作)
*/
class TCPServe{
public static void main(String[] args) throws Exception{
ServerSocket ss =new ServerSocket(10009);
while(true){
Socket sk =ss.accept();
String ip =sk.getInetAddress().getHostAddress();
FileOutputStream fos=new FileOutputStream("2.bmp");
InputStream ips =sk.getInputStream();
byte[] buf=new byte[1024];
int len;
while((len=ips.read(buf))!=-1){
fos.write(buf, 0, len);
}
OutputStream out=sk.getOutputStream();
out.write("上传成功".getBytes());
sk.close();
}
}} |