你的位置:首页 > Java教程

[Java教程]利用TCP 客户端


首先盲写的一个传输文件的方法,但测试发现了一个非常不容易发现的问题,这里先说明一下。

错误的代码如下:

 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.成功复制文件并打印友好回馈