简体   繁体   English

Java套接字读写意外行为

[英]Java Socket read and write unexpected behavior

I faced an issue while transferring file from client to server. 从客户端到服务器传输文件时遇到问题。 So I did a simple client and server code in java using sockets. 所以我在Java中使用套接字做了一个简单的客户端和服务器代码。 I found some unexpected behavior. 我发现了一些意外的行为。 I can't find why it happens so. 我找不到为什么会这样。 Following is the code 以下是代码

Server side code: 服务器端代码:

import java.io.*;
import java.net.*;

class Server
{
  public static void main(String args[])
  {
    ServerSocket ser;
    try {
        ser=new ServerSocket(9000);
        Socket cnfcon=ser.accept();
        OutputStream outstr=cnfcon.getOutputStream();
        InputStream inpstr=cnfcon.getInputStream();
        PrintWriter out=new PrintWriter(outstr,true);
        BufferedReader inp=new BufferedReader(new InputStreamReader(inpstr));
        File f=new File("test.txt");
        InputStream fis= new FileInputStream(f);
        long size=f.length();
        System.out.println("Start Server");
        out.println(f.getName());
        out.println(size);
        byte[] buff1=new byte[]{0,1,2,3,4,5,6,7,8,9};
        byte[] buff2=new byte[]{7,1,2,3,8,5,6,7,8,9};

        outstr.write(buff1);
        //inpstr.read(); -- tried including this and removing this
        outstr.write(buff2);
        //inpstr.read();


        fis.close();
        inp.close();
        ser.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
  }
 };

client side code: 客户端代码:

import java.io.*;
import java.net.*;

class test
{
    public static void main(String args[]) throws UnknownHostException, IOException
    {
    Socket cnfcon=new Socket("127.0.0.1",9000);
    OutputStream outstr=cnfcon.getOutputStream();
    InputStream inpstr=cnfcon.getInputStream();
    PrintWriter out=new PrintWriter(outstr,true);
    BufferedReader inp=new BufferedReader(new InputStreamReader(inpstr));

    File f=new File(inp.readLine()+"t"); //"t" - dummy
    f.createNewFile();
    FileOutputStream fos=new FileOutputStream(f);

    int size=Integer.parseInt(inp.readLine());
    byte buff[]=new byte[1024];


    System.out.println("Start Client");

    inpstr.read(buff, 0, 10);
    disp(buff);
    //outstr.write(1); -- tried including this and removing this
    inpstr.read(buff, 0, 10);
    disp(buff);
    //outstr.write(1); 1 - dummy value


    fos.close();
    out.close();
    cnfcon.close();

}
public static void disp(byte buff[])
{
    for(int i=0;i<10;i++)
        System.out.print(buff[i]);
    System.out.println();
}
};

I am sending two buffers from server to client. 我正在从服务器到客户端发送两个缓冲区。

Here I expect first buffer should come first and next for next time. 在这里,我希望第一个缓冲区应该排在第一位,下一次要在下一个缓冲区。 But its unpredictable. 但其变化莫测。

Some times it works as expected. 有时它会按预期工作。 Some times it gets the 2nd buff for both time. 有时它会同时获得第二个buff。 Some times all bytes in the buffer are zero. 有时,缓冲区中的所有字节均为零。

I tried adding outstr.flush() before the message passing. 我尝试在消息传递之前添加outstr.flush()。

Is there any other way to implement this? 还有其他方法可以实现吗?

To be more clear, it seems client is not waiting for server to send or vice versa. 更明确地说,似乎客户端没有在等待服务器发送,反之亦然。

The output is different every time. 每次输出都不同。

Suggestions are appreciated. 建议表示赞赏。

The problems are at least two: 问题至少有两个:

  1. You're ignoring the count returned by read() , and assuming it filled the buffer. 您将忽略read()返回的计数,并假设它已填充缓冲区。 It isn't obliged to do that. 它没有义务这样做。 It isn't contracted to transfer more than one byte. 传输的字节数不超过一个字节。 You have to loop: 您必须循环:

     while ((count = in.read(buffer)) > 0) { out.write(buffer, 0, count); } 
  2. Data is disappearing into the buffered readers/writers/streams, and it is caused by using too many parts of the I/O stack. 数据消失在缓冲的读取器/写入器/流中,这是由于使用了I / O堆栈的过多部分所致。 Don't use multiple readers, writers, and streams, on the same socket. 不要在同一套接字上使用多个读取器,写入器和流。 Use a single output stream or writer and a single input stream or reader for the life of the socket. 在套接字的生存期内,请使用单个输出流或写入器以及单个输入流或读取器。 As you are writing binary data you shouldn't be using readers or writers at all. 在编写二进制数据时,您根本不应该使用读取器或写入器。

Contrary to other answers here, it isn't necessary to add flushes or sleeps in this code, as long as you close everything correctly, or to fiddle around with available() results either. 与这里的其他答案相反,只要正确地关闭所有内容,或者摆弄available()结果,就不必在代码中添加刷新或休眠。

Try adding a Thread.sleep() in the client when it receives the buffers? 尝试在客户端收到缓冲区时在客户端添加Thread.sleep()吗? Not sure if it will work. 不知道是否会工作。

Let me guess , you are on Microsoft windows ? 让我猜猜,您正在使用Microsoft Windows?

First chunk your data into small chunks ( let's say 1kb ), but you are already doing that and then sleep a little bit in both your read and write loops. 首先将数据分成小块(比如说1kb),但是您已经在执行此操作,然后在读取和写入循环中都睡了一点。 Call flush when possible after writes, and Be sure to make sure you don't read more than input stream.availible() 写入后在可能的情况下调用flush,并确保未读超过输入流。availible()

Your code should work on every other os without issue , without modification. 您的代码应该可以在其他操作系统上正常工作,而无需修改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM