TCP客户端/服务器只接收前两条消息

时间:2014-08-15 15:04:45

标签: java sockets tcp client bukkit

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

这是服务器代码

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插件

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

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

server.start();

然后客户端,这是一个自定义的Minecraft客户端

client.Connect();

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

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

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

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

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

客户端将首先向客户端发送消息,请求播放器套件

GETKIT <player-name>

服务器将接收该内容,然后发送回相关数据

KIT <player-name> <kit-name>

然后客户端将收到与上面相同的内容。然而,客户端每400毫秒向服务器发送大约6个请求,然后服务器将相应地做出响应,但问题是客户端将只收到服务器第一次发送的第一个2消息,然后是每个其他请求 - 没有被客户收到。

2 个答案:

答案 0 :(得分:0)

试试这个:(客户)

sock.setKeepAlive(true);

答案 1 :(得分:0)

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