图片上传:
首先,在这里我描述以下,我在实现图片上传时遇到的问题。
1、首先运行服务端,然后运行客户端,服务器端输出提示:图片已接收完毕,但是客户端并没有接收到服务器端的响应结果,我仔仔细细的走了一遍流程,最后发现是在客户端上传完图片的时候,刷新输出管道,关闭本地输入管道之后,需要主动将socket管道shutdowmOutput
// 通知服务器端,客户端已经上传完毕。
socket.shutdownOutput();
这样子服务器端才能知道你的文件上传完毕,才能往下执行发送给客户端响应消息的代码,否则若客户端为shutdonw掉socket的管道,服务器端会一直以为你还在给它传数据,但其实管道里面没有字节在传输,但是output管道还是通的,服务器代码就不会往下执行。
2、第二个问题就是,既然是使用ip访问本机服务器,那么非本机是否也是可以通过本机外网的ip访问到自己本机的服务器,那么我就用室友的电脑试了一试(由于服务器不是在公网ip上,所以两台电脑要在同一个wifi下才可以),但是怎样也连接不上,于是我就使用cmd去在室友的电脑上ping自己电脑的ip是可以ping通的,那么就不是室友的电脑问题,那自然也不是代码的问题,因为自己电脑上开了好几个客户端都可以成功。最后经过工作室的老师的提示下,发现自己电脑的防火墙是全开着的(windows10)
可以看到,三个防火墙都是开着的,注意的是有一个防火墙显示(使用中),一定要关闭这个防火墙,室友的电脑才可以成功将图片上传至你的服务器。(很有气人的一件事就是,一开始我将域网络的防火墙关了,发现还是不行,然后辗转反侧才发现有个使用中的防火墙开着,我灵机一动,将他一贯,非本机客户端一运行,ok了,真的是茅塞顿开的感觉,就喜欢这种成就感)
若有不懂,联系qq:1620460256,无偿帮助,共同进步!!!
具体实现代码如下:
客户端代码实现:
/**
* 文件上传
* 客户端
* 服务端 IP:127.0.0.1 端口:7777
* SRC_FILE: D:\相册\头像\2.jpg
* DEST_FILE: D:\相册\服务器图片仓库
*/
public class FileUploadClient {
public static String SRC_FILE = "D:\\相册\\头像\\2.jpg";
public static void main(String[] args) throws Exception {
System.out.println("=======客户端启动======");
System.out.println(InetAddress.getLocalHost());
// 1、请求服务器socket管道
Socket socket = new Socket("192.168.137.1", 6655);
// 2、冲socket管道中获取一个字节输出流
OutputStream os = socket.getOutputStream();
// 3、将低级的输出流包装成高级的字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(os);
// 4、读取本地的文件到bos中,复制
System.out.println("文件名称为:"+new File(SRC_FILE).getName());
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(SRC_FILE));
// 5、读多少倒多少
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
bos.flush();
bis.close();
System.out.println("客户端已将文件数据上传完毕!");
// 通知服务器端,客户端已经上传完毕。
socket.shutdownOutput();
// 接收服务器响应消息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// System.out.println(br);
System.out.print("服务器响应消息:");
System.out.println(br.readLine());
}
}
8.2 服务器端代码实现
服务端采用了多线程为每个客户端管道分配一个线程,上传文件,当然这样子的方式在项目中是不可取的,因为一旦客户端太多,服务器会因为创建线程维护线程的运行太多,而宕机,这里仅仅是为了实现图片上传的代码
public class FileUploadServer {
public static String DEST_FILE = "D:\\相册\\服务器图片仓库\\";
public static void main(String[] args) throws Exception{
System.out.println("=====服务端启动======");
// 1、先创建服务器管道 socket
ServerSocket serverSocket = new ServerSocket(6655);
while(true){
// 2、等待接收客户端 socket
Socket socket = serverSocket.accept();
System.out.println("用户信息"+socket);
// 2.1 为当前客户端管道分配一个独立的线程来处理通信
new ServerReadThread(socket).start();
}
}
}
// 线程代码
public class ServerReadThread extends Thread {
private Socket socket;
public ServerReadThread(Socket socket){
this.socket = socket;
// System.out.println(socket);
}
@Override
public void run() {
try{
// 3、从socket获取字节输入流
InputStream is = socket.getInputStream();
System.out.println(socket.getRemoteSocketAddress()+"上线了");
// 4、将低级的字节输入流包装成高级的字节输入流
BufferedInputStream bis = new BufferedInputStream(is);
// 5、获取本地的文件输出流,将接收到的文件写入本地文件夹中
FileOutputStream os = new FileOutputStream(DEST_FILE + UUID.randomUUID().toString()+".jpg");
System.out.println("新文件名为:"+DEST_FILE + UUID.randomUUID()+".jpg");
// 6、创建一个本地文件输出流
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
// 刷新、关闭本地IO管道
bos.flush();
bos.close();
// 服务器响应接收成功结果
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("亲爱的客户端,你上传的图片,我已接收完毕!");
ps.flush();
Thread.sleep(1000);
}catch (Exception e){
System.out.println(socket.getRemoteSocketAddress()+"下线了");
}
}
}