4

サーバー側のソケット処理コードを書きましたが、パケットが常にクライアントに返されるとは限らないのではないかと心配しています。すべてのイベントをログに記録していますが、ログ ファイルに情報を送信していると表示されます。しかし、クライアントはイベントもログに記録しており、ログには何も受信していないと書かれています。

データを送信するための私のコードは次のとおりです。

public void write(Packet packet) {
    String data = packet.serialize();
    log("Send=[" + data + "]", "Write"); // log to file

    try {
        _writer.write(data);
        _writer.flush();
    } catch (Exception ex) {
        log(ex, "write");
    }
}

各ソケットは新しいスレッドで作成され、ライターとリーダーを次のようにすぐに作成します (public run メソッドで):

// _sockt is a Java Socket object
_writer = new BufferedWriter(new OutputStreamWriter(_socket
                    .getOutputStream()));
            _reader = new SocketReader(_socket);

SocketReader は、応答をリッスンするために作成した単なるラッパー クラスであり、次のような public read メソッドがあります。

public String read() throws IOException, SocketTimeoutException {

    _socket.setSoTimeout(_timeOut);

    if(_reader == null)
        _reader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));

            // read from the stream
    return new PacketDataInputStream(_reader).read();
}

PacketDataInputStream ラッパー クラス:

BufferedReader _reader = null;

public PacketDataInputStream(BufferedReader reader)
{
    _reader = reader;
}

public String read() throws IOException, SocketException {

    StringBuilder builder = new StringBuilder();
    int c = 0;

    while((c = _reader.read()) != -1)
    {
        char ch = (char)c;

        builder.append(ch);

        if(ch == PacketConstants.ETX)
            break;
    }

    if(builder.length() > 0)
        return builder.toString();
    else
        return null;

}

実際のソケットリスナーオブジェクトを作成する方法は、かなり標準的だと思います:

InetAddress address = InetAddress.getByName(IP);
        server = new ServerSocket( port, 0, address);

                    // My own manager class to handle all the sockets connected 
        WebSocketManager manager = new WebSocketManager(this);

        Socket connection = null;

        while(bContinue)
        {
            connection = server.accept();

            if(bContinue) {
                                    // assign the socket to a new thread and start
                                    // that thread
                manager.newSocket(connection);  
            } else {
                connection.close();
            }
        }
  • データを送り返すために間違ったオブジェクトを使用している可能性があります。
  • bufferedwriter と reader を使用する必要がありますか? これらが最善の方法だと思っていましたが、今はよくわかりません。

これは常に発生するわけではなく、散発的に発生することに注意することが重要です。クライアントのコードにバグがある可能性がありますが、クライアントに戻る前に、正しく実行していることを確認する必要があります。

このコードは、Linux Ubuntuサーバーで実行されます。ログはテキスト ファイルに記録されますが、特別なことは何もありません。私のログ ファイルには、Send=""データがクライアントに返され、例外がないことが示されているため、.write と .flush() が機能したように見えますか? ソケット接続は永続的であり、クライアントまたはネットワークの問題によってのみ閉じられます。

更新 ----- クライアント側のコード -------:

私は、データの送受信をどのように処理しているかについて、クライアント側のコードの一部を取得することができました (念のため、クライアント側でより明白な場合に備えて)。クライアントは、実際にはAndroid デバイスを介してこのサーバーに接続しています(それが役立つ場合)。

ソケットの作成

static final int BUFFER_SIZE = 20000;       // Maximum packet size

java.net.InetAddress server = java.net.InetAddress.getByName(url);
socket = new Socket(server, port);
// Set socket options:
socket.setReceiveBufferSize(BUFFER_SIZE);
socket.setSendBufferSize(BUFFER_SIZE);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);

送信:

try {
            // Send the packet:
        OutputStream stream = socket.getOutputStream();
        stream.write(p.getByteArray ());
        stream.flush();

            // Update the time:
        lastPacketSendTime = new Date ();
    } catch (IOException e) {
        setError("Error sending packet (" + e.getMessage() + ")", ERROR_IO);
        return false;
    }

受信:

socket.setSoTimeout(timeout);
            // Get the reader:
        inputStream = socket.getInputStream();



     while (true) {
                    // Get the next character:
                int value = inputStream.read();
                    // Check for -1, indicating that the socket is closed:
                if (value == -1) {
                        // The socket is closed remotely, so close it locally as well:
                    disconnect();
                    inputStream = null;
                    return null;
                }
                                // ... and a bunch of other stuff to handle the actual data

                        }

EDIT 14-11月: これは実際には、より大きな問題であることが証明されています. クライアント ログとサーバー ログの両方が送信されているようです。しかし、データが届かないように見えたり、届いたとしても 10 ~ 30 ~ 60 秒遅れて届くことがあります。

必要に応じて、さらに情報を提供できます。

4

2 に答える 2

1

これがあなたの用途になるかどうかはわかりませんが、クライアントサーバー通信に使用したコードを提供します。

クライアント側:

public class ClientWala {

    public static void main(String[] args) throws Exception{

        Boolean b = true;
    Socket s = new Socket("127.0.0.1", 4444);

    System.out.println("connected: "+s.isConnected());


    OutputStream output = s.getOutputStream();
    PrintWriter pw = new PrintWriter(output,true);

    // to write data to server
    while(b){

        if (!b){

             System.exit(0);
        }

        else {
            pw.write(new Scanner(System.in).nextLine());
        }
    }


    // to read data from server
    InputStream input   = s.getInputStream();
    InputStreamReader isr = new InputStreamReader(input);
    BufferedReader br = new BufferedReader(isr);
    String data = null;

    while ((data = br.readLine())!=null){

        // Print it using sysout, or do whatever you want with the incoming data from server

    }




    }
}

サーバーコード:

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


public class ServerTest {

    ServerSocket s;

    public void go() {

        try {
            s = new ServerSocket(44457);

            while (true) {

                Socket incoming = s.accept();
                Thread t = new Thread(new MyCon(incoming));
                t.start();
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    class MyCon implements Runnable {

        Socket incoming;

        public MyCon(Socket incoming) {

            this.incoming = incoming;
        }

        @Override
        public void run() {

            try {
                PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
                        true);
                InputStreamReader isr = new InputStreamReader(
                        incoming.getInputStream());
                BufferedReader br = new BufferedReader(isr);
                String inp = null;

                boolean isDone = true;

                System.out.println("TYPE : BYE");
                System.out.println();
                while (isDone && ((inp = br.readLine()) != null)) {

                    System.out.println(inp);
                    if (inp.trim().equals("BYE")) {
                        System.out
                                .println("THANKS FOR CONNECTING...Bye for now");
                        isDone = false;
                        s.close();
                    }

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                try {
                    s.close();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new ServerTest().go();

    }

}
于 2012-06-22T20:08:21.127 に答える
1

BufferedReaders と BufferedWriters を使用すると、バッファリングされます。入力ストリームと出力ストリームを直接使用するのはどうですか。また、ライターは文字ベースです。バイナリデータを送信する必要があるかどうかはわかりませんが、そうであればライターの問題になります。

于 2012-06-22T19:49:07.737 に答える