Java Socket读写意外行为

时间:2015-02-09 23:31:39

标签: java sockets client-server

我在将文件从客户端传输到服务器时遇到了问题。所以我使用套接字在java中做了一个简单的客户端和服务器代码。我发现了一些意外的行为。我无法找到原因。以下是代码

服务器端代码:

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();
    }
  }
 };

客户端代码:

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();
}
};

我从服务器向客户端发送两个缓冲区。

在这里,我希望第一个缓冲区首先出现,下一次出现下一个缓冲区。 但它无法预测。

有时它按预期工作。有时它会同时获得第二次buff。有时缓冲区中的所有字节都为零。

我尝试在传递消息之前添加outstr.flush()。

还有其他方法可以实现吗?

更清楚的是,客户端似乎没有等待服务器发送,反之亦然。

每次输出都不同。

建议表示赞赏。

3 个答案:

答案 0 :(得分:2)

问题至少有两个:

  1. 您忽略了read()返回的计数,并假设它填充了缓冲区。它没有义务这样做。它不签约传输超过一个字节。你必须循环:

    while ((count = in.read(buffer)) > 0)
    {
        out.write(buffer, 0, count);
    }
    
  2. 数据正在消失在缓冲的读取器/写入器/流中,这是由于使用I / O堆栈的太多部分引起的。不要在同一个套接字上使用多个读取器,写入器和流。在插槽的生命周期中使用单个输出流或写入器以及单个输入流或读取器。在编写二进制数据时,根本不应该使用读者或编写者。

  3. 与此处的其他答案相反,没有必要在此代码中添加刷新或睡眠,只要您正确关闭所有内容,或者使用available()结果来摆弄。

答案 1 :(得分:-1)

尝试在收到缓冲区时在客户端添加Thread.sleep()?不确定它是否会起作用。

答案 2 :(得分:-2)

让我猜一下,你在微软的Windows上?

首先将数据块分成小块(比方说1kb),但是你已经这样做了,然后在你的read和write循环中稍微睡一觉。写入后尽可能调用flush,并确保不要读取输入stream.availible()

您的代码应该可以在没有问题的情况下在所有其他操作系统上运行,