首先盲寫的一個傳輸文件的方法,但測試發現了一個非常不容易發現的問題,這裡先說明一下。
錯誤的代碼如下:
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.成功復制文件並打印友好回饋
*4.第二天在同一局域網上的兩台機器上測試,竟然不好使,尚未未找到原因,看到這篇博客的希望給點兒建議~