首先盲写的一个传输文件的方法,但测试发现了一个非常不容易发现的问题,这里先说明一下。
错误的代码如下:
1 package com.TCP.java; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.OutputStream; 10 import java.net.InetAddress; 11 import java.net.ServerSocket; 12 import java.net.Socket; 13 14 import org.junit.Test; 15 16 //从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。并关闭相应的连接。 17 public class TestTCP3 { 18 //客户端 19 @Test 20 public void client(){ 21 Socket socket = null; 22 OutputStream os = null; 23 FileInputStream fis = null; 24 InputStream is = null; 25 try { 26 //创建一个Socket的对象 27 socket = new Socket(InetAddress.getByName("192.168.1.101"),9090); 28 //从本地获取一个文件发送给服务端 29 os = socket.getOutputStream(); 30 fis = new FileInputStream(new File("findLei.jpg")); 31 byte[] b = new byte[1024]; 32 int length; 33 while((length = fis.read(b)) != -1){ 34 os.write(b,0,length); 35 } 36 socket.shutdownOutput(); 37 //接收来自服务端的信息 38 is = socket.getInputStream(); 39 byte[] b1 = new byte[1024]; 40 int length1; 41 while((length1 = is.read(b1)) != -1){ 42 String str = new String(b1,0,length1); 43 System.out.println(str); 44 } 45 }catch (IOException e) { 46 e.printStackTrace(); 47 } 48 finally{ 49 //关闭相应的流和Socket对象 50 if(is != null){ 51 try { 52 is.close(); 53 } catch (IOException e) { 54 e.printStackTrace(); 55 } 56 } 57 if(fis != null){ 58 try { 59 fis.close(); 60 } catch (IOException e) { 61 e.printStackTrace(); 62 } 63 } 64 if(os != null){ 65 try { 66 os.close(); 67 } catch (IOException e) { 68 e.printStackTrace(); 69 } 70 } 71 if(socket != null){ 72 try { 73 socket.close(); 74 } catch (IOException e) { 75 e.printStackTrace(); 76 } 77 } 78 } 79 } 80 81 //服务端 82 @Test 83 public void server(){ 84 ServerSocket ss = null; 85 Socket s = null; 86 InputStream is = null; 87 FileOutputStream fos = null; 88 OutputStream os = null; 89 try { 90 //创建一个ServerSocket的对象 91 ss = new ServerSocket(9090); 92 //调用accept()方法,返回一个Socket对象 93 s = ss.accept(); 94 //将从客户端发送的信息保存到本地 95 is = s.getInputStream(); 96 fos = new FileOutputStream("D:/Test"); 97 // Random random = new Random(); 98 // fos = new FileOutputStream("D:/Test/" + String.valueOf(random.nextInt(90)) + ".jpg"); 99 // fos = new FileOutputStream("find2.jpg"); 100 byte[] b = new byte[1024]; 101 int length; 102 while((length = is.read(b)) != -1){ 103 fos.write(b, 0, length); 104 } 105 //发送接收成功的消息 106 os = s.getOutputStream(); 107 os.write("接收成功".getBytes()); 108 } catch (FileNotFoundException e) { 109 e.printStackTrace(); 110 } catch (IOException e) { 111 e.printStackTrace(); 112 } 113 finally{ 114 //关闭相应的流及ServerSocket,Socket对象 115 if(os != null){ 116 try { 117 os.close(); 118 } catch (IOException e) { 119 e.printStackTrace(); 120 } 121 } 122 if(fos != null){ 123 try { 124 fos.close(); 125 } catch (IOException e) { 126 e.printStackTrace(); 127 } 128 } 129 if(is != null){ 130 try { 131 is.close(); 132 } catch (IOException e) { 133 e.printStackTrace(); 134 } 135 } 136 if(s != null){ 137 try { 138 s.close(); 139 } catch (IOException e) { 140 e.printStackTrace(); 141 } 142 } 143 if(ss != null){ 144 try { 145 ss.close(); 146 } catch (IOException e) { 147 e.printStackTrace(); 148 } 149 } 150 } 151 } 152 }
有看出来问题么,没有,看着一点问题也没有,但执行的时候就是报错,而且报错的位置着实很头痛,在那附近找了很久也没找到......
下面是所报Error的信息
1 java.net.SocketException: Software caused connection abort: socket write error 2 at java.net.SocketOutputStream.socketWrite0(Native Method) 3 at java.net.SocketOutputStream.socketWrite(Unknown Source) 4 at java.net.SocketOutputStream.write(Unknown Source) 5 at com.TCP.java.TestTCP3.client(TestTCP3.java:35) 6 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 7 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 8 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 9 at java.lang.reflect.Method.invoke(Unknown Source) 10 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 11 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 12 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 13 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 14 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 15 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 16 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 17 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 18 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 19 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 20 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 21 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 22 at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 23 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 24 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 25 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 26 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) 27 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 28 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
指定的位置是35行写入的问题,但是找了很久也没找到原因,还要感谢我大姚哥帮我找到了这个问题
先说明一下这个Error的意思,大概就是Socket在写入的时候出现故障了,调查这段代码的过程就不一一详述了,就说一下真正的原因在哪,真正的原因是server端需要写入的文件夹目录有问题,我写的是fos = new FileOutputStream("D:/Test");这个路径在直接写入文件的时候有问题,这里进行复制的时候需要指定其格式,及其命名,这个路径明显缺少这两样,而如果改成相对路径就没有那么麻烦了,fos = new FileOutputStream("find2.jpg");这样执行就成功了,但如果我们想将文件放在指定目录下呢,可以用这种方式
Random random = new Random();
fos = new FileOutputStream("D:/Test/" + String.valueOf(random.nextInt(90)) + ".jpg")
这种方式可以自动添加一个随机数,使其避免了重命名的风险,反正问题是已经解决了,成功代码只需打开注释即可
下面说明一下此TCP传输可以实现的功能
1.选中server(服务端),用JUnit启动。当传输文件时服务一定要先开启啊,这是常识
2.选中client(客户端),用JUnit启动。其中这里有两个参数是需要手动改的,一个是IP,即你想要传输到的电脑(这台电脑要启动server)的IP;另一个就是端口号,这个是自己随便命名的,像Tomcat一样也需要一个端口号(Tomcat是8080)。
3.成功复制文件并打印友好回馈