楼主能加注释尽量要加注释啊!这样别人就很容易看出的你的代码想要做什么了.
目前我发现有两处错误
1,在服务端你同时nowSocket.getInputStream()));两次获取客户端的套接字节流,可能是这造成了部分字节数据丢失.
2,你的客户端中有两次向服务器发送数据,但中间过程你只做了flush()刷新动作.等于第一次客户端的套接输入流实际上服务端并没有收到.你应该在每次写完数据后进行一次套接输入流关闭动作.而服务上你也有两次获取客户端的套接字读取流,中间过程你不仅没有关闭服务端接受客户端的写入流,造成知道服务端最后执行nowSocket.shutdownInput();的时候全部数据才涌进来.所以就会出现你上传后的文件和源文件大小不同等原因.
下面是我同样功能的代码,你看下吧:- public class TcpImage {
- public static void main(String[] ages) {
- // 客户端
- new Thread(new Runnable() {
- //创建服务端套接字
- Socket sk = null;
- //定义文件读取流
- FileInputStream fis = null;
- public void run() {
- try {
- sk = new Socket(InetAddress.getByName("192.168.16.41"),
- 2008);
- OutputStream os = sk.getOutputStream();
- //将服务获取的读取流转换成字符流
- BufferedReader bisr = new BufferedReader(
- new InputStreamReader(sk.getInputStream()));
- //获取原文件的读取流
- fis = new FileInputStream("E:\\Images\\1.jpg");
- byte[] bt = new byte[1024];
- int end;
- while ((end = fis.read(bt)) != -1) {
- os.write(bt, 0, end);
- }
- //关闭客服端的写入流 这不非常重要 如果没有关闭该流 则数据不会发送到服务端
- sk.shutdownOutput();
- String line;
- while ((line = bisr.readLine()) != null) {
- System.out.println(line);
- }
- } catch (Exception e) {
- throw new RuntimeException("客户端异常退出");
- } finally {
- if (fis != null) {
- try {
- fis.close();
- } catch (IOException e) {
- throw new RuntimeException("客户端服务关闭异常");
- }
- }
- if (sk != null) {
- try {
- sk.close();
- } catch (IOException e) {
- throw new RuntimeException("客户端服务关闭异常");
- }
- }
- }
- }
- }).start();
- // 服务端
- new Thread(new Runnable() {
- //创建一个服务套接字
- ServerSocket ssk = null;
- FileOutputStream fos = null;
- public void run() {
- try {
- ssk = new ServerSocket(2002);
- fos = new FileOutputStream("F:\\1_copy.jpg");
- //获取服务端接受到的客户套接字
- Socket sk = ssk.accept();
- //获取客户套接字的读取流对象
- InputStream br = sk.getInputStream();
- BufferedWriter bw = new BufferedWriter(
- new OutputStreamWriter(sk.getOutputStream()));
- byte[] bt = new byte[1024];
- int endr;
- while ((endr = br.read(bt)) != -1) {
- fos.write(bt, 0, endr);
- }
- bw.write(sk.getInetAddress()+"成功上传");
- bw.newLine();
- bw.flush();
- //关闭服务端接受的客户端套接字的写入流 这个步骤也非常重要 如果没有该步 那么服务端线程将处于线程等待机制
- sk.shutdownOutput();
- } catch (IOException e) {
- throw new RuntimeException("服务端异常退出");
- } finally {
- if (fos != null) {
- try {
- fos.close();
- } catch (IOException e) {
- throw new RuntimeException("服务写入流关闭异常");
- }
- }
- if (ssk != null) {
- try {
- ssk.close();
- } catch (IOException e) {
- throw new RuntimeException("服务关闭异常");
- }
- }
- }
- }
- }).start();
- }
- }
复制代码 |