繁体   English   中英

Java套接字读写意外行为

[英]Java Socket read and write unexpected behavior

从客户端到服务器传输文件时遇到问题。 所以我在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()。

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

更明确地说,似乎客户端没有在等待服务器发送,反之亦然。

每次输出都不同。

建议表示赞赏。

问题至少有两个:

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

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

与这里的其他答案相反,只要正确地关闭所有内容,或者摆弄available()结果,就不必在代码中添加刷新或休眠。

尝试在客户端收到缓冲区时在客户端添加Thread.sleep()吗? 不知道是否会工作。

让我猜猜,您正在使用Microsoft Windows?

首先将数据分成小块(比如说1kb),但是您已经在执行此操作,然后在读取和写入循环中都睡了一点。 写入后在可能的情况下调用flush,并确保未读超过输入流。availible()

您的代码应该可以在其他操作系统上正常工作,而无需修改。

暂无
暂无

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

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