服务器段代码/**
 * 将response信息发送到socket客户端
 * 
 * @param response
 */
private void writeSocket() {
try { OutputStream outs = socket.getOutputStream();
DataOutputStream douts = new DataOutputStream(outs);
douts.write("123456".getBytes());
douts.write("aabbcc".getBytes());
douts.write("eeffgg".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
客户端代码System.out.println("socket client write byte[] finished");
InputStream ins = socket.getInputStream();
DataInputStream dins = new DataInputStream(ins);
byte[] aa = new byte[12];
dins.read(aa);
//byte[] bb = new byte[6];
//dins.read(bb);
byte[] cc = new byte[6];
dins.read(cc);
System.out.println(new String(aa));
//System.out.println(new String(bb));
System.out.println(new String(cc));客户端结果
123456      
aabbcc其中123456 后边有6个空的字符,字节里值是0

解决方案 »

  1.   

    但是服务器写的顺序和客户端读的顺序,字节数一致时,读的正常。
    不是说read方法会阻塞吗?
    我试验服务器不给客户端传输数据,客户端直接read,它还是没有阻塞,直接就执行过去了哪位知道呢?
      

  2.   

    因为 server端已经先把数据发回开户端了,所以客户端读的时候就步用等了(因为已经有数据读了啊)
      

  3.   

    是阻塞,但是你就read了一次哇
    一般都是while(true) {
    read();//这里阻塞,没有东西就停在这里,这才是阻塞的含义
    }
      

  4.   

    写入流没flush
    所有的流都没有close
      

  5.   

    只要读到流的末尾,read方法就返回了如果没有东西可以读,就一直阻塞在那,也就是等在那
      

  6.   

    我那段代码如果在执行read之前打个断点,停顿一下,然后在继续,就没有问题,
    byte[] aa = new byte[12];
                dins.read(aa);
     这段就能读出12个字节,否则就读到服务端第一次写的6个字节的内容这个怎么理解?
      

  7.   

    1."我试验服务器不给客户端传输数据,客户端直接read,它还是没有阻塞,直接就执行过去了", 个人认为是步可能的,除非连接已经断开。
    2."但是服务器写的顺序和客户端读的顺序,字节数一致时,读的正常。" 我觉得步一致时,应该也正常。最后 "eeffgg"客户端根本就没有读,当然打印不出来。3.关于后面补0问题,
     byte[] aa = new byte[12];
     dins.read(aa);
    现在有6个字节让你读,你要读12个,所以只能后面六个补0了。   
      

  8.   

    写入流没flush
    所有的流都没有close
    写入流没flush
    所有的流都没有close
    写入流没flush
    所有的流都没有close
    写入流没flush
    所有的流都没有close
    写入流没flush
    所有的流都没有close
    写入流没flush
    所有的流都没有close
    写入流没flush
    所有的流都没有close
    写入流没flush
    所有的流都没有close
      

  9.   

    我在
     byte[] aa = new byte[12];
     dins.read(aa);
    这段代码前打个断点,停顿下,就能读到12个字节的内容,否则就只读到6个字节的,怎么解释呢?
      

  10.   

    就是Server跟客户端工作时序的问题,如果Server已经写入了12个自己,然后客户端读,就当然可以读到12个。可以连调Server,Client,都设断点交互调试。
      

  11.   

    我试验服务器不给客户端传输数据,客户端直接read,它还是没有阻塞,直接就执行过去了你上面的意思是你把
                douts.write("123456".getBytes());
                douts.write("aabbcc".getBytes());
                douts.write("eeffgg".getBytes());
    这三行代码注释掉对吗?那么你注释后有没有重启服务器呢
      

  12.   

    while(true) {
    read();//这里阻塞,没有东西就停在这里,这才是阻塞的含义
    }这个没有参数的read的话 一次只读取一个字节吗,内容读到哪里呢?
      

  13.   


    不是,在  private void writeSocket() {   里面加断点。
      

  14.   

    to xiesisi3:
    “既然加了断点那么程序还没执行到这一步就不会写进去东西,那么肯定也就是读不到东西的.”我认为客户端会停在read上面,就是楼主需要的样子。“用了多线程?” 楼主是个server,client的程序,Server跟Client都补在一个JVM, 就这个问题场景而言,目前不涉及多线程问题。
      

  15.   

    关于 Socket编程,有个完整的例子供楼主参考.
    http://mybeautiful.javaeye.com/blog/659317
      

  16.   


    你没看清楚LZ的回复吧..LZ的意思是,在调用writeSocket()这个方法之前还设置了断点,但客户端还是能读到东西,所以我才回复肯定是哪里出了问题,因为这不合乎正常的逻辑.我说的多线程,不是指客户端和服务器位于两个不同的线程,它们之间的关系是进程间的关系,和线程无关.
    我说的多线程,是指LZ是不是在服务器端使用了多线程,其中一个线程就调用了writeSocket()这个方法,但他是在另外一个线程里加了断点,自然就起不到效果了.
      

  17.   

    各位下班了吗?我再贴一次完整的吧
    服务端public class Server2 extends Thread {
    Socket socket; public Server2(Socket socket, String uuid) {
    super(uuid);
    this.socket = socket;
    } @Override
    public void run() {
    System.out.println("running..");
    try {
    this.writeSocket();
    } catch (Exception ioe) {
    ioe.printStackTrace();
    } finally {
    this.closeSocket();
    }
    } /**
     * 将response信息发送到socket客户端
     * 
     * @param response
     */
    private void writeSocket() {
    try { OutputStream outs = socket.getOutputStream();
    DataOutputStream douts = new DataOutputStream(outs);
    /*douts.write("123456".getBytes());
    douts.write("aabbcc".getBytes());
    douts.write("eeffgg".getBytes());
    douts.flush();*/
    } catch (IOException e) {
    e.printStackTrace();
    }
    } /**
     * 一个线程处理完后,关闭socket连接
     */
    public void closeSocket() {
    try {
    this.socket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    } public static void main(String args[]) {
    ServerSocket serverSocket = null;
    try {
    serverSocket = new ServerSocket(9999);
    System.out.println("服务成功启动了!");
    } catch (IOException e) {
    e.printStackTrace();
    }
    while (true) {
    try {
    Socket socket = serverSocket.accept();
    System.out.println("接收到一个客户端请求!");
    UUID uuid = UUID.randomUUID();
    Server2 sp = new Server2(socket, uuid.toString());
    sp.start();
    sp.join();// 主线程要等待该线程终止。
    } catch (Exception ne) {
    ne.printStackTrace();
    }
    }
    }
    }客户端public class SocketClient2 extends Thread {
    @Override
    public void run() {
    try {
    byte[] ww = "<root></root>".getBytes();

    Socket socket = new Socket("localhost",9999);
    // socket.setSoTimeout(0);//无限期等待

    OutputStream outs = socket.getOutputStream();
    //报文头
    outs.write(ww);
    //报文内容
    outs.flush();
    System.out.println("socket client write byte[] finished");
    InputStream ins = socket.getInputStream();
    DataInputStream dins = new DataInputStream(ins);
    byte[] aa = new byte[12];
    dins.read(aa);
    //byte[] bb = new byte[6];
    //dins.read(bb);
    byte[] cc = new byte[6];
    dins.read(cc);
    System.out.println("socket client read byte[] finished");
    System.out.println(new String(aa));
    //System.out.println(new String(bb));
    System.out.println(new String(cc));
    } catch(Exception e) {
    e.printStackTrace();
    }

    }
    public static void main(String args[]) throws Exception {
    SocketClient2 t = new SocketClient2();
    t.start();
    }
    }
    问题还是那个问题,麻烦再看看吧,是不是socket过早给关闭了引起的?
      

  18.   

    dins.readFully(aa);
    dins.readFully(cc);
    这样才对,read方法可能只是读取一小部分,它的返回值就是表示读取了多少个字节。
      

  19.   

    readFully的话,注释掉服务端的write代码,就会报EOF异常
    java.io.EOFException
    at java.io.DataInputStream.readFully(Unknown Source)
    at java.io.DataInputStream.readFully(Unknown Source)
    at socket.SocketClient2.run(SocketClient2.java:32)
      

  20.   

    readFully 服务端如果正常分次write的话,确实能读到足够的字节信息,我看了readFully的源代码
    while (n < len) {
        int count = in.read(b, off + n, len - n);
        if (count < 0)
    throw new EOFException();
        n += count;
    }确实是循环着读够的但是我仍然感觉不到block(阻塞)呢
      

  21.   

    那是肯定啊,服务器并没有发送足够的字节当然报错。
    你必须定义好双方的约定,才可以在一开始的时候知道服务器会发送多少数据到客户端中如果是读取所有数据:
    byte[] buff = new byte[1024];
    int readed;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    while((readed = dis.read(buff)) > 0)
        baos.write(buff, 0, readed);
    System.out.println(baos.toString());
      

  22.   

    你所谓的阻塞是指服务器还没有发送数据的时候,客户端会一直处于等待如果服务器都已经关闭连接了,当然不会继续等下去。服务器在closeSocket之前调用System.in.read(),你客户端再 使用我上面的代码就会发现它停在了read方法上了,直到服务器继续发数据或者关闭连接。
      

  23.   

    DataInputStream.read(byte[]) 这个方法并不一定返回参数指定数组长度的字节的。
    你需要根据返回值确定读了多少字节。
    不设断点的时候,第一次其实只读取了6个字节。
    至于为什么只读取了6个字节,我觉得这跟javaIO,操作系统IO实现有关。比如read在读了6个字节了,等了一段时间(非常短)后,发现没有新的字节过来,就先把这6个字节返回了。你看不到阻塞是因为服务端处理很快,你感觉不出来而已。