-2

マルチプレイヤー ゲームで問題が発生しています。現在、サーバーに現在のレベルをクライアントに送信させようとしています。サーバーは間違いなくデータを送信していますが、クライアント アプリケーションには到達しません。

クライアントコード:

    public void run() {
    while(true)
    {
        try {
            sel.select();
            Set readyKeys = sel.selectedKeys();
            Iterator itr = readyKeys.iterator();
            while(itr.hasNext())
            {
                SelectionKey key = (SelectionKey) itr.next();
                itr.remove();
                SocketChannel ch = (SocketChannel) key.channel();
                if(key.isReadable())
                {
                    inputbuf.clear();
                    long bytesRead = ch.read(inputbuf);
                    inputbuf.flip();
                    byte[] test = inputbuf.array();
                    {
                        for(int i=0; i < inputbuf.remaining(); i++)
                        {
                           System.out.print(test[i]+" ");
                        }
                    }
                    byte cmd = 0;
                    cmd = inputbuf.get();
                    switch(cmd)
                    {
                        case 1:
                           //do something
                        case 2:
                           //do something else
                        break;
                    }
                }
                else if(key.isConnectable())
                {
                    sc.finishConnect();
                    sc.register(sel, SelectionKey.OP_READ);
                }
            }
        } catch (IOException ex) {
            Buildsim.error("Error handling input from server", ex);
        }
    }
}

サーバーコード:

public RemotePlayer(SocketChannel s)
{
    sc = s;
    try {
        sel = Selector.open();
        sc.configureBlocking(false);
        sc.register(sel, SelectionKey.OP_WRITE);
        socket = sc.socket();
        ip = socket.getInetAddress().toString();
        System.out.println("New connection from "+ip);
        inputbuf = ByteBuffer.allocate(1048576);
        outputbuf = ByteBuffer.allocate(1048576);
        inputbuf.clear();
        outputbuf.clear();
    }
    catch(Exception e)
    {
        Buildsim.error("Connection error: ", e);
    }
    sendLevel();
}
public void sendObject(GameObject obj)
{
     //Sends a packet of the object, then does the same for the object's children
}
public void sendLevel()
{
    try {
        outputbuf.put((byte) 0x01);
        outputbuf.flip();
        sc.write(outputbuf);
        sendObject(Buildsim.w.parts.get(0)); //root object
    }
    catch(IOException e)
    {
        Buildsim.error("Error sending level to "+ip, e);
    }
}

クライアントに到達するのは、バイト 0x01 (レベル変更を通知する) だけです。

前もって感謝します。

4

1 に答える 1

0

あなたが私たちに提供してくれた情報の量では、次のようなグローバルなヒントしか提供できません: ソケット ストリームがバッファリングされていないこと、およびflush()情報が書き込まれた後であることを確認しましたか?

データは、送信されるためにいっぱいになるのを待っているバッファで待機している可能性があります。

編集:

SocketChannel を非ブロッキング モードに設定したので、送信側でフラッシュを処理すると仮定するのは正しいことです。クライアントは入力をバッファリングしないと思いますか?

問題は、SocketChannel.write()がバッファ全体を書き込むことを保証されていないことですが、早期に戻る可能性があります。データが実際にチャネルに書き込まれることを確認するために、書き込まれたバイトを追跡するために、while ループで書き込みをラップする必要があります。Javadoc を引用するには:

特に指定がない限り、書き込み操作は、要求されたすべてのバイトを書き込んだ後にのみ返されます。 一部のタイプのチャネルは、その状態に応じて、一部のバイトのみを書き込むか、まったく書き込まない場合があります。たとえば、非ブロッキング モードのソケット チャネルは、ソケットの出力バッファで空き容量を超えるバイト数を書き込むことはできません。

于 2010-01-31T21:58:55.447 に答える