我正在为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消息,然后是每个其他请求 - 没有被客户收到。
答案 0 :(得分:0)
试试这个:(客户)
sock.setKeepAlive(true);
答案 1 :(得分:0)
你没有显示任何端口号,所以我要问,端口号是否等于bukkit服务器?因为它不能...