2

このプログラムが正しく動作しないのはなぜですか? クライアントは SOME_MESSAGE を読み取り、その後は何も起こりません。サーバーからの println メソッドが何らかの形で long 型の数値の転送に影響を与えているようです。

サーバ

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

public class Server {

  public static void main(String[] args) throws Exception {
    ServerSocket socket = new ServerSocket(9999);
    while (true) {
      Socket sock = socket.accept();
      PrintWriter out = new PrintWriter(new BufferedWriter(
          new OutputStreamWriter(sock.getOutputStream())), true);
      DataOutputStream outByte = new DataOutputStream(sock.getOutputStream());
      out.println("SOME_MESSAGE");
      outByte.writeLong(948L);
    }
  }
}

クライアント

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

public class Client {

  public static void main(String[] args) throws Exception {
    Socket sock = new Socket("127.0.0.1", 9999);
    DataInputStream inByte = new DataInputStream(sock.getInputStream());
    BufferedReader in = new BufferedReader(new InputStreamReader(
        sock.getInputStream()));

    System.out.println(in.readLine());
    long number = inByte.readLong();
    System.out.println(number);
  }
}
4

2 に答える 2

3

問題は、がソケットの入力ストリームからバイトをバッファリングしているため、が読み取ってバッファリングしているBufferedReaderため、長い 948 値が にないことです。一般に、特に 1 つがバッファリングされている場合、同じ基になるストリームに対して 2 つの異なるラッパーを使用することは望ましくありません。クラスと同じですが、少なくとも機能しているようです。DataInputStreamBufferedReaderServer

クライアントは、ソケットの入力ストリームに 1 つのラッパーのみを使用する必要があります。と をDataInputStreamサーバー コードと一緒に使用DataInputStream.readUTF()し、クライアントで使用し、サーバーで使用して、とDataOutputStream.writeUTF()の両方を削除する必要があります。BufferedReaderPrintWriter

サーバー上で:

while(true) {
    Socket sock = socket.accept();
    DataOutputStream outByte = new DataOutputStream(sock.getOutputStream());
    outByte.writeUTF("SOME_MESSAGE");
    outByte.writeLong(948L);
    outByte.flush();

}

そしてクライアント上で:

public static void main(String[]args)throws Exception
{
    Socket sock = new Socket("127.0.0.1",9999);
    DataInputStream inByte = new DataInputStream(sock.getInputStream());

    System.out.println(inByte.readUTF());
    long number  = inByte.readLong();
    System.out.println(number);
}
于 2012-08-20T08:46:44.047 に答える
0

興味深いのは、常により良い解決策があると言って、Java がそれを許可していないことです。シリアル化を使用してジョブを実行できます。

PayLoad以下のようなインターフェースを作成します

import java.io.Serializable;


public interface PayLoad extends Serializable
{
String getMessage();
//Java does not allow to define byte array of long
int getLength();

byte[] getbytes();

}

次に、以下のような実装クラスを作成します

public class FilePayLoad implements PayLoad
{

private final String message;
private final int length;
private final byte[] bytes;

public FilePayLoad(String message, int length, byte[] bytes)
{
    this.message = message;
    this.length = length;
    this.bytes = bytes;

}

@Override
public String getMessage()
{
    return this.message;
}

@Override
public int getLength()
{
    return this.length;
}

@Override
public byte[] getbytes()
{
    return this.bytes;
}

}

サーバーとクライアントを以下のように変更します

サーバ

public class Server
{

public static void main(String[] args) throws Exception
{
    ServerSocket socket = new ServerSocket(9999);
    while (true)
    {
        Socket sock = socket.accept();
        ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
        byte[] bytes = "SOME_MESSAGE".getBytes();
        out.writeObject(new FilePayLoad("SOME_MESSAGE", bytes.length, bytes));
        out.flush();
    }
}
}

クライアント

public class Client
{
public static void main(String[] args) throws Exception
{
    Socket sock = new Socket("127.0.0.1", 9999);
    ObjectInputStream inByte = new ObjectInputStream(sock.getInputStream());
    PayLoad payLoad = (PayLoad) inByte.readObject();
    System.out.println(payLoad.getMessage());
    System.out.println(payLoad.getLength());
    System.out.println(new String(payLoad.getbytes()));
}

}
于 2012-08-20T10:27:48.387 に答える