TCP网上传输文件

本篇主要是一些案列的实现

案例1

在这里插入图片描述
思路图
在这里插入图片描述
代码
服务端

package yuan.hsp.net.TranFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
@SuppressWarnings({"all"})
public class Server {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//服务端叫ServerSocket,在8888端口监听
		ServerSocket serverSocket = new ServerSocket(8888);
		System.out.println("在8888端口等待链接");
		//等待链接
		Socket accept = serverSocket.accept();
		//先创建这个输入流,读取数据,处理流包
		BufferedInputStream In = new BufferedInputStream(accept.getInputStream());
		//由于我们之前已经写了输入流变成字符数组的方法直接用
		byte[] STA = StreamUtils.StreamTOByteArray(In);
		//(相对路径)创建输出流输出文件,还是处理流包
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src\\66.png"));
		bos.write(STA);//写入
		System.out.println("服务端传输文件完成");
		
		
		//然后介绍输出客户端:收到图片
		BufferedWriter b = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
		b.write("收到图片");
		b.flush();//这个底层才是发送数据
		accept.shutdownInput();//如果用这个作为停止标志,那么接收方是可以用字节流接收字符流传输的数据的
		
		
		//这两个流也要最后关闭,不然你写入的数据Cilent读不到,不知道为啥,感觉写网络就最后把流都关闭一下吧
		In.close();
		bos.close();
		
		b.close();
		accept.close();
		serverSocket.close();
		System.out.println("服务端退出");
		
		
	}

}

客户端

package yuan.hsp.net.TranFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
@SuppressWarnings({"all"})
//传输文件客户端
//这里我写一个工具类StreamUtils,具体作用自己去看
public class Cilent {
	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket socket = new Socket(InetAddress.getLocalHost(),8888);
		byte [] b=new byte[1024];//创建字节接收文件
		
		//创建一个把文件输入到我们客户端的流,用处理流包下文件节点流
		BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("d:\\ykj.png"));
		//运用工具类,把我们的字节输入流输入的数据转为字节数组
		byte[] streamTOByteArray = StreamUtils.StreamTOByteArray(bufferedInputStream);
		
		//创建向服务端输送数据的流,这里还是用到这个处理流反正以后就用处理流就对了
		BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
		bos.write(streamTOByteArray);//写入字节数组
		
		bufferedInputStream.close();//可以把那个文件输入流关闭了
		
		socket.shutdownOutput();//注意,字节流输入要这个结束标记
		
		
		InputStream inputStream = socket.getInputStream();//还是我们能把一个输入数据转换为字节数组,就那个工具类,既然写了就多用
		System.out.println(new String(StreamUtils.StreamTOByteArray(inputStream)));
		
		
		//关闭
		bos.close();//注意,这个不要中间关闭,会报错
		socket.close();
		System.out.println("客户端退出");
		
		
		
		
	}

}

工具类(输入字节流转换为字节数组)

package yuan.hsp.net.TranFile;


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;



//工具类
public class StreamUtils {
public static byte[] StreamTOByteArray(InputStream i) throws IOException {//接收一个输入流对象,把这个对象传输的数据转换为一个字节数组
	//创建一个字节数组输出流,因为最后可以转换成一个字节数组
	ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
	
	byte b[]=new byte[1024];
	int len;
	while((len=i.read(b))!=-1) {
		byteArrayOutputStream.write(b,0,len);
	}
	byte[] array=byteArrayOutputStream.toByteArray();
	byteArrayOutputStream.close();
	
	return array;
	
}
}

对应效果
服务端
在这里插入图片描述
客户端
在这里插入图片描述
文件传输效果
在这里插入图片描述
注意:等到最后再把所有流一起close,不然会出现许多难以想象的错误

关于TCP网络通讯的小秘密

在这里插入图片描述
在这里插入图片描述
就是客户端也会分配一个端口来和程序段连接

程序验证(netstate)

用我们上面写的程序,可以直接运行服务端
然后
在这里插入图片描述
关于本机8888端口只有这一个
如果运行客户端
除了上面那个
在这里插入图片描述

还会多一个这个,注意我们在本机netstat查看网络状况,是以本机为服务端的!
然后我们的服务端是8888端口
这个60285端口其实就是客户端随机分配的端口

服务器端口是创建ServerSocket就确定的
客户端就是TCP/IP随机分配的

小知识

byte[] b这样直接b.toString()
是不能显示我们原本的内容的(如果有中文)
需要new String(b,0,len)

具体可以看
关于new String(byte [])和byte[].toSring()和Arrays.toString(byte [])的区别

还有只要是Buffered用了处理流,不过你是字节流还是字符流,只要是输出的流,你想写入都要flush()不然不会写入成功

下面这个例子就是惨痛教训

案列2

在这里插入图片描述
客户端

package yuan.hsp.net.TranFile;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
@SuppressWarnings({"all"})
//文件下载客户端
public class downloadCilent {
	public static void main(String[] args) throws IOException {
		Socket socket = new Socket(InetAddress.getLocalHost(),6666);
		Scanner scanner = new Scanner(System.in);
		System.out.println("输入你想要下载的歌");
		String next = scanner.next();
		
		BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
		outputStream.write(next.getBytes()); 
		outputStream.flush();//注意只要用处理流,最后一定要刷新!!!
		//还要注意一定要结束!!!
		socket.shutdownOutput();
		
		
		byte[] streamTOByteArray = StreamUtils.StreamTOByteArray(socket.getInputStream());
		
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
				new FileOutputStream("d:\\喜欢的音乐.mp3"));
		
		bufferedOutputStream.write(streamTOByteArray);
		
		
		bufferedOutputStream.close();
		socket.close();
		scanner.close();
		
		System.out.println("客户端退出");
		
		
		
		
	}

}

服务端

package yuan.hsp.net.TranFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.NonWritableChannelException;
import java.util.Scanner;

import yuan.learn.basic.Multithreading.interrupt_;
@SuppressWarnings({"all"})
//文件下载服务端
public class downloadServer {
public static void main(String[] args) throws IOException {
	ServerSocket serverSocket = new ServerSocket(6666);
	System.out.println("服务端在6666端口等待");
	Socket accept = serverSocket.accept();
	
	BufferedInputStream InputStream = new BufferedInputStream(accept.getInputStream());
	byte[] array = StreamUtils.StreamTOByteArray(InputStream);
	String Array = new String(array, 0, array.length);
	
	
	
	System.out.println("需要查找的文件是"+Array);
	//传输文件肯定是字节流
	BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(accept.getOutputStream());
	
	String name = "";
	if(Array.equals("Ferrari")) {
	name="d:\\CloudMusic\\Bebe Rexha - Ferrari.mp3";
	}
	else {
		name="d:\\CloudMusic\\周星星 - 足够.mp3";
	}
	BufferedInputStream bufferedInputStream = new BufferedInputStream(
			new FileInputStream(name));
	
	byte[] Array02 = StreamUtils.StreamTOByteArray(bufferedInputStream);
	
	bufferedOutputStream.write(Array02);
	accept.shutdownOutput();
	
	//关闭,后开的资源先关闭
	bufferedInputStream.close();
	bufferedOutputStream.close();
	accept.close();
	serverSocket.close();
	System.out.println("服务端退出");
	
	
	
}
}

运行结果
服务端
在这里插入图片描述客户端
在这里插入图片描述

惨痛教训主要就是
1.服务端卡着不动-因为没有设计客户端输出结束标志(socket.shutdownOutput)
2.输出的文件是乱码,用byte[].toString(),这个方法本质是是用的Object所以没有重写就是原来那个字节数组
3.换成new String后,文件输出为空白
主要是处理流(不管是字节还是字符)都要flush()我没有写flush()然后就没有成功写入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小袁拒绝摆烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值