简体   繁体   中英

TCP client/server only receives first two messages

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.

This is the server code

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();
}
}

Then this is the client code

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;
}
}

This is the socket handler class

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();
}
}

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();

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());

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>

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.

试试这个:(客户端)

sock.setKeepAlive(true);

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM