客户端接收服务端的反馈,根据响应码打印相应信息。
进入下一次循环,接着读取用户命令。
客户端:这里还出现了一个致命bug,即最后再写出的时候,最后一次循环异常阻塞。
public class FileSocketClient {
public static void main(String[] args) {
Socket socket=null;
InputStream is=null;
OutputStream os=null;
//服务器ip地址
String serverIp="127.0.0.1";
//服务器端端口号
int port=21;
//下载文件
String filename="d.txt";
try {
//建立连接
socket=new Socket(serverIp,port);
//支持多次数据交换
for (int i=0; i<3; i++) {
//发送数据
os = socket.getOutputStream();
os.write(filename.getBytes());
//接收反馈数据
is = socket.getInputStream();
OutputStream fos = new FileOutputStream(filename);
byte[] b = new byte[1024];
int n = 0;
n = is.read(b);
String response = new String(b, 0, n);
String[] entry = response.split(":");
if (entry.length == 2) {
if (entry[1].equals("504"))
System.out.println("文件不存在!");
if (entry[1].equals("332"))
System.out.println("请先注册!");
} else {
while (-1 != n) {
//fos:外部文件
fos.write(b);
//is:服务器反馈
n = is.read(b); //最后一次读取后直接结束程序
}
System.out.println("下载成功");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
//关闭流和链接
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务端:
public class FileSocketServer {
public static void main(String[] args) throws InterruptedException {
ServerSocket serverSocket=null;
Socket socket=null;
OutputStream os=null;
InputStream is=null;
//监听端口号
int port=21;
//文件根目录
String path="data/";
try {
//监听端口
serverSocket=new ServerSocket(port);
//获得客户端连接;进入这一步的执行时会等待客户端
socket=serverSocket.accept();
//接收客户端发送内容
is=socket.getInputStream();
os = socket.getOutputStream();
byte[] b=new byte[1024];
//支持多次数据交换
for (int i=0; i<3; i++) {
int n = is.read(b);
String filename = new String(b, 0, n);
//反馈
String response = "status:";
response = download(path + filename, os);
//下载失败
if (response != "200") {
response = "status:" + response;
os.write(response.getBytes());
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//关闭流和连接
is.close();
os.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static String download(String filename,OutputStream os) {
BufferedInputStream bis=null;
try {
bis = new BufferedInputStream(new FileInputStream(filename));
byte[] b=new byte[1024];
int n=0;
while (-1!=(n=bis.read(b))){
os.write(b,0,n);
}
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
return "504";
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//注意!一定要先检查bis是否为null,
//当文件不存在时,创建bis失败,其为null,
//直接执行关闭操作会抛出无法捕获的异常
if(bis!=null) {
bis.close();
}
//抛FileNotFoundException后,执行完这一步,
//直接跳出main的for循环执行main的finally
} catch (IOException e) {
e.printStackTrace();
}
}
return "200";
}
}
专门处理请求的线程:
public class LogicThread extends Thread {
Socket socket;
InputStream is;
OutputStream os;
public LogicThread(Socket socket) {
this.socket = socket;
//启动线程
start();
}
@Override
public void run() {
byte[] b=new byte[1024];
try {
os=socket.getOutputStream();
is=socket.getInputStream();
//进行多次数据交换,客户端应该相应地也发出这么多次数据
for (int i=0; i<3; i++){
//接收数据
int n=is.read(b);
//处理数据
byte[] response=logic(b,0,n);
//反馈
os.write(response);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流和连接
close();
}
}
/**
* @Author haien
* @Description 处理数据,实际就是直接拷贝
* @Date 2019/6/26
* @Param [b, start, len]
* @return byte[]
**/
public byte[] logic(byte[] b,int start,int len){
byte[] response=new byte[len];
//直接拷贝数组
System.arraycopy(b,0,response,0,len);
return response;
}
/**
* @Author haien
* @Description 关闭流和连接
* @Date 2019/6/26
* @Param []
* @return void
**/
public void close(){
try {
is.close();
os.close();
socket.close();
} catch (IOException e) {
}
}
}
代码示例:ideaProjects/jar-test/ftp