TCP客户端/服务器仅接收前两个消息

问题描述:

我正在为bukkit设置服务器/客户端交互.定制的Minecraft客户端将通过套接字将数据发送到服务器,服务器将读取该数据并将消息发送回客户端.客户端和服务器的套接字具有相同的代码,但是客户端使用客户端类,服务器使用服务器.

I am setting up a server/client interaction for bukkit. The custom minecraft client will send data over a socket to the server which will read that data and send a message back to the client. Both client and server have the same code for the sockets, however the client uses the client class and the server the server.

这是服务器代码

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import com.cmg.sapphire.sockets.events.ServerSocketAccepted;
import com.cmg.sapphire.sockets.events.ServerSocketAcceptedEvent;
import com.cmg.sapphire.sockets.events.ServerSocketStarted;
import com.cmg.sapphire.sockets.events.ServerSocketStartedEvent;
import com.cmg.sapphire.sockets.events.SocketHandlerReadyEvent;
import com.cmg.sapphire.sockets.events.SocketHandlerReadyEventListener;

public class Server extends Thread {

private int port;

private int counter = 0;

private List<SocketHandler> handlers = new ArrayList<SocketHandler>();

private ServerSocket server;

private ServerSocketStarted started;
private ServerSocketAccepted accepted;

public Server(int port) {

    this.port = port;

    this.started = new ServerSocketStarted();
    this.accepted = new ServerSocketAccepted();

}

private void StartListening() {

    try {

        server = new ServerSocket(port);

        started.executeEvent(new ServerSocketStartedEvent(this));

        while (true) {

            Socket sock = server.accept();

            final SocketHandler handler = new SocketHandler(sock, ++counter);

            handler.getReady().addSocketHandlerReadyEventListener(
                    new SocketHandlerReadyEventListener() {

                        @Override
                        public void socketHandlerReady(
                                SocketHandlerReadyEvent evt) {
                            accepted.executeEvent(new ServerSocketAcceptedEvent(
                                    this, handler));
                        }

                    });

            handler.start();

            handlers.add(handler);

        }

    } catch (IOException e) {
        e.printStackTrace();
    }

}

public void ShutdownAll() {

    for (SocketHandler handler : handlers) {
        handler.Disconnect();
    }

    handlers.clear();

}

public void StopServer() {
    try {
        server.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public SocketHandler[] getHandlers() {
    return handlers.toArray(new SocketHandler[handlers.size()]);
}

public SocketHandler getHandler(int index) {
    return handlers.get(index);
}

public ServerSocketStarted getServerSocketStarted() {
    return started;
}

public ServerSocketAccepted getSocketAccepted() {
    return accepted;
}

@Override
public void run() {
    StartListening();
}
}

然后这是客户端代码

import java.net.Socket;

public class Client {

private Socket sock;

private SocketHandler handler = new SocketHandler();

private String host;
private int port;

public Client(String host, int port) {
    this.host = host;
    this.port = port;
}

public void Connect() {
    try {
        sock = new Socket(host, port);

        handler.setSocket(sock);
        handler.setID(0);

        handler.start();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public synchronized void SendMessage(String message) {
    handler.SendMessage(message);
}

public void Disconnect() {
    handler.Disconnect();
}

public SocketHandler getHandler() {
    return handler;
}

public Socket getSocket() {
    return sock;
}
}

这是套接字处理程序类

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;

import com.cmg.sapphire.main.PvpDojoClient;
import com.cmg.sapphire.sockets.events.MessageReceived;
import com.cmg.sapphire.sockets.events.MessageReceivedEvent;
import com.cmg.sapphire.sockets.events.SocketConnected;
import com.cmg.sapphire.sockets.events.SocketConnectedEvent;
import com.cmg.sapphire.sockets.events.SocketDisconnected;
import com.cmg.sapphire.sockets.events.SocketDisconnectedEvent;
import com.cmg.sapphire.sockets.events.SocketHandlerReady;
import com.cmg.sapphire.sockets.events.SocketHandlerReadyEvent;

public class SocketHandler extends Thread {

private Socket sock;

private int bytesReceived = 0;
private int messageSize = -1;

private byte[] buffer = new byte[4];

private InputStream in;
private OutputStream out;

private SocketConnected connected;
private SocketDisconnected disconnected;
private MessageReceived message;
private SocketHandlerReady ready;

private String hostName;

private int id;

public SocketHandler() {
    this.disconnected = new SocketDisconnected();
    this.message = new MessageReceived();
    this.connected = new SocketConnected();
    this.ready = new SocketHandlerReady();
}

public SocketHandler(Socket sock, int id) {
    this.sock = sock;
    this.id = id;

    this.connected = new SocketConnected();
    this.disconnected = new SocketDisconnected();
    this.message = new MessageReceived();
    this.ready = new SocketHandlerReady();

}

private void HandleConnection() {
    if (sock == null) {
        return;
    }

    try {
        this.hostName = sock.getInetAddress().getCanonicalHostName();

        in = sock.getInputStream();
        out = sock.getOutputStream();

        if (in == null || out == null) {
            Disconnect();
            return;
        }

        ready.executeEvent(new SocketHandlerReadyEvent(this, this));
        connected.executeEvent(new SocketConnectedEvent(this, this, id));

        startReading();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public synchronized void SendMessage(String message) {
    if (sock.isConnected() && !sock.isClosed()) {
        writeToStream(message);
    }
}

private void startReading() {
    if (!sock.isConnected() || sock.isClosed()) {
        Disconnect();
        return;

    }

    buffer = new byte[buffer.length - bytesReceived];

    try {
        if (bytesReceived == -1) // end of stream
        {
            Disconnect();
            return;
        }

        bytesReceived += in.read(buffer);

        if (messageSize == -1) // still reading size of data
        {
            if (bytesReceived == 4) // received size information
            {
                messageSize = ByteBuffer.wrap(buffer).getInt(0);

                if (messageSize < 0) {
                    throw new Exception();
                }

                buffer = new byte[messageSize];

                bytesReceived = 0;
            }

            if (messageSize != 0) // need more data
            {
                startReading();
            }
        } else {
            if (bytesReceived == messageSize) // message body received
            {
                StringBuffer sb = new StringBuffer();
                sb.append(new String(buffer));

                message.executeEvent(new MessageReceivedEvent(this, id, sb
                        .toString()));

                // reset
                bytesReceived = 0;
                messageSize = -1;
                buffer = new byte[4];

                startReading(); // start reading again
            } else
            // need more data
            {
                startReading();
            }
        }
    } catch (Exception e) {

    }
}

private void writeToStream(String message) {
    if (!sock.isConnected() || sock.isClosed() || out == null)
        return;

    byte[] sizeinfo = new byte[4];

    byte[] data = message.getBytes();

    ByteBuffer bb = ByteBuffer.allocate(sizeinfo.length);
    bb.putInt(message.getBytes().length);

    try {
        out.write(bb.array());
        out.write(data);
        out.flush();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public void Disconnect() {
    try {
        System.out.println("Client disconnecting");

        sock.shutdownInput();
        sock.shutdownOutput();

        sock.close();

        disconnected.executeEvent(new SocketDisconnectedEvent(this, id));
    } catch (Exception e) {
        e.printStackTrace();
    }

}

public void setSocket(Socket sock) {
    this.sock = sock;
}

public void setID(int id) {
    this.id = id;
}

public String getHostName() {
    return hostName;
}

public SocketConnected getConnected() {
    return connected;
}

public SocketDisconnected getDisconnected() {
    return disconnected;
}

public MessageReceived getMessage() {
    return message;
}

public Socket getSocket() {
    return sock;
}

public SocketHandlerReady getReady() {
    return ready;
}

public void run() {
    if (this.sock == null)
        return;

    HandleConnection();
}
}

最后要设置服务器,我有一个运行该代码的bukkit插件

Finally to setup the server i have a bukkit plugin which runs this code

server.getSocketAccepted().addServerSocketAcceptedEventListener(
            new ServerSocketAccepted());

server.getServerSocketStarted().addServerSocketStartedEventListener(
            new ServerSocketStarted());

server.start();

然后是客户端,这是在自定义的minecraft客户端中

then the client, this is in a custom minecraft client

client.Connect();

client.getHandler().getConnected()
            .addSocketConnectedEventListener(new SocketConnectedToServer());

client.getHandler().getMessage()
            .addMessageReceivedEventListener(new MessageReceived());

client.getHandler().getDisconnected()
            .addSocketDisconnectedEventListener(new SocketDisconnected());

要从服务器向客户端发送消息,反之亦然,我将在SocketHandler类中调用SendMessage方法.

To send a message from the server to the client or vice versa i would call the SendMessage method in the SocketHandler class.

现在的问题是,当我尝试向客户端发送消息时,客户端只会收到前两条消息.

Now the problem is that when i try and send a message to the client, the client will only receive the first two messages.

客户首先会向客户发送一条消息,要求像这样的球员装备

The client will first send a message to the client requesting the players kit like so

GETKIT <player-name>

服务器将收到该消息,然后像这样发送回相关数据

The server will receive that and then send back the relevant data like so

KIT <player-name> <kit-name>

然后,客户端将收到与上述相同的内容.但是,客户端每400毫秒向服务器发送大约6个请求,然后服务器将做出相应的响应,但是问题是客户端将仅接收服务器首次发送的前2条消息,然后才接收其他每个请求-没有被客户收到.

Then the client will receive the same thing as above. However the client sends around 6 requests to the server every 400 ms, then the server will respond accordingly, but the problem is the client will ONLY RECEIVE THE FIRST 2 MESSAGES sent by the server for the first time, then for every other request - nothing is received by the client.

您没有显示任何端口号,所以我想问一下,该端口号是否等于bukkit服务器?因为它不能...

You don't show any port number so I'm going to ask, is the port number equal to the bukkit server?Because it cannot be...