【发布时间】:2014-06-21 17:19:23
【问题描述】:
我正在编写游戏,但现在我遇到了服务器/客户端套接字的问题。当我在本地玩游戏以及使用 RMI 在线玩游戏时,该游戏运行良好。当我尝试实现套接字时出现问题(我也必须做套接字)。这就是我实现代码的方式(我使用模型-视图-控制器模式):
服务器: SocketServerCreate类:创建服务器,然后创建一个线程来接收连接(SocketServerConnection),然后创建另一个线程来接收所有客户端的消息(SocketServerReceive)。服务器还实例化了一个对象,该对象实现了模型调用的 Observer 以向客户端发送信息(SocketServerOutput)。
客户: SocketClientCreate类:打开与服务端的连接,然后创建一个线程接收服务端消息,并实例化一个实现观察者的类,视图调用该观察者向服务端发送信息。
问题是SocketServerOutput类中的Server的update方法被调用了很多次,但必须只调用一次才能将消息发送给客户端。需要说明的是,我发布了服务器和客户端的所有代码。
SocketServerCreate
/*
* This class creates the server.
*/
public class SocketServerCreate {
private static final int PORT = 5000;
private ArrayList<ObjectOutputStream> arrayPlayerSocket;
private SocketServerOutput outputServer;
public SocketServerCreate(Model model){
ServerSocket serverSocket;
Controller controller = new Controller(model);
arrayPlayerSocket = new ArrayList<ObjectOutputStream>();
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
System.out.println("Error during the creation of the Server.\n" + e.getStackTrace());
return;
}
outputServer = new SocketServerOutput(this, controller);
SocketServerConnection connectionServer = new SocketServerConnection(this, serverSocket, controller);
Thread receiveServerThread = new Thread(connectionServer);
receiveServerThread.start();
}
public void addPlayerSocket(ObjectOutputStream outputStream){
arrayPlayerSocket.add(outputStream);
}
public ArrayList<ObjectOutputStream> getArrayPlayerSocket(){
return (ArrayList<ObjectOutputStream>) arrayPlayerSocket;
}
public SocketServerOutput getSocketServerOutput(){
return outputServer;
}
}
SocketServerOutput
/*
* This class manages the object that must be send to the client.
*/
public class SocketServerOutput implements Observer {
ArrayList<ObjectOutputStream> arrayPlayersSocket;
SocketServerCreate socketServerCreate;
Controller controller;
private ObjectOutputStream outputMessage = null;
public SocketServerOutput(SocketServerCreate socketServerCreate, Controller controller){
this.socketServerCreate = socketServerCreate;
this.controller = controller;
}
@Override
public void update(Observable o, Object arg) {
if(o.equals(controller.getModel().getModelChanges())){
arrayPlayersSocket = socketServerCreate.getArrayPlayerSocket();
Iterator<ObjectOutputStream> arrayIterator = arrayPlayersSocket.iterator();
while(arrayIterator.hasNext()){
outputMessage = (ObjectOutputStream)arrayIterator.next();
try {
outputMessage.writeObject(arg);
outputMessage.flush();
/*if(arrayPlayersSocket.indexOf(outputMessage) != controller.getTurn().getCurrentPlayer()){
ModelChanges modelChanges = new ModelChanges();
modelChanges.spegniBottoniOnLine(false, false, false);
outputMessage.writeObject(modelChanges);
outputMessage.flush();
}*/
} catch (IOException e) {
System.out.println("IOException while the server sends an object to the client!");
return;
}
}
}
}
}
SocketServerConnection
public class SocketServerConnection implements Runnable {
private ServerSocket serverSocket;
private SocketServerCreate socketServerCreate;
private Controller controller;
public SocketServerConnection(SocketServerCreate socketServerCreate, ServerSocket serverSocket, Controller controller){
this.socketServerCreate = socketServerCreate;
this.serverSocket = serverSocket;
this.controller = controller;
}
@Override
public void run() {
while(true){
try {
Socket lastSocket = serverSocket.accept();
ObjectOutputStream outputMessage = new ObjectOutputStream(lastSocket.getOutputStream());
socketServerCreate.addPlayerSocket(outputMessage);
//send to the view the index where the client is setted in the server array
outputMessage.writeObject((Integer)socketServerCreate.getArrayPlayerSocket().lastIndexOf(outputMessage));
outputMessage.flush();
SocketServerReceive receiveServer = new SocketServerReceive(lastSocket, controller);
Thread receiveThread = new Thread(receiveServer);
receiveThread.start();
} catch (IOException e) {
System.out.println("IOException while the server accept the client.\n" + e.getCause());
}
}
}
}
SocketServerReceive
public class SocketServerReceive implements Runnable {
private ObjectInputStream inputMessage = null;
private Controller controller;
private Object message;
public SocketServerReceive(Socket socket, Controller controller){
this.controller = controller;
System.out.println("Connection created with the client that has IP Address: " + socket.getInetAddress());
if(inputMessage == null){
try {
inputMessage = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
System.out.println("IOException while the server are creating a stream with the client.\n" + e.getCause());
}
}
}
@Override
public void run() {
while(true){
try {
message = inputMessage.readObject();
controller.receiveMessageView(message);
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException in SocketServerReceive.\n" + e.getStackTrace());
return;
} catch (IOException e) {
}
}
}
}
SocketClientCreate
/*
* This class starts a connection with the Server and then it creates two threads,
* one to manage the input request, the other to manage the output request
*/
public class SocketClientCreate {
private static final int PORT = 5000;
private Socket serverSocket;
private int arrayIndex;
private SocketClientOutput outputClient;
public SocketClientCreate(String ipAddress, View view){
try {
serverSocket = new Socket(ipAddress, PORT);
} catch (UnknownHostException e) {
System.out.println("UnknownHostException during the connection of the Client at the Server");
return;
} catch (IOException e) {
System.out.println("IOException during the connection of the Client at the Server");
return;
}
outputClient = new SocketClientOutput(this, serverSocket, view);
SocketClientReceive receiveClient = new SocketClientReceive(this, serverSocket, view);
Thread receiveThread = new Thread(receiveClient);
receiveThread.start();
}
public SocketClientOutput getOutputClient(){
return outputClient;
}
public void setArrayIndex (Integer arrayIndex){
this.arrayIndex = arrayIndex;
}
public int getArrayIndex(){
return arrayIndex;
}
}
SocketClientOutput
/*
* This class manages all the message that the client must send to the server. Its methods
* are called by update method.
*/
public class SocketClientOutput implements Observer {
private ObjectOutputStream outputMessage = null;
private View view;
private SocketClientCreate socketClientCreate;
public SocketClientOutput(SocketClientCreate socketClientCreate, Socket server, View view){
this.view = view;
this.socketClientCreate = socketClientCreate;
if(outputMessage == null){
try {
outputMessage = new ObjectOutputStream(server.getOutputStream());
} catch (IOException e) {
System.out.println("IOException at the opening of the output stream between the client and the server.\n" + e.getCause());
return;
}
}
}
/*
* update receive an object from the view and send this object to the server.
*/
@Override
public void update(Observable o, Object arg) {
if(o.equals(view)){
/*
* GESTIRE INDICE CREAZIONE GIOCATORE
*/
try {
outputMessage.writeObject(arg);
outputMessage.flush();
} catch (IOException e) {
System.out.println("IOException while the client sends an object to the server.\n" + e.getCause());
return;
}
}
}
}
SocketClientReceive
/*
* This class waits an object from the server and then modify the view.
*/
public class SocketClientReceive implements Runnable {
private ObjectInputStream inputMessage = null;
private View view;
private SocketClientCreate socketClientCreate;
private Object message;
public SocketClientReceive(SocketClientCreate socketClientCreate, Socket server, View view){
this.view = view;
this.socketClientCreate = socketClientCreate;
if(inputMessage == null){
try {
inputMessage = new ObjectInputStream(server.getInputStream());
} catch (IOException e) {
System.out.println("IOException at the opening of the input stream between the client and the server.\n"+e.getStackTrace());
}
}
}
@Override
public void run() {
while(true){
try {
message = inputMessage.readObject();
if(message instanceof Integer){
socketClientCreate.setArrayIndex((Integer)message);
}else if(message instanceof ModelChanges){
ModelChanges modelChanges = (ModelChanges)message;
view.getMappa().repaintView(modelChanges);
}
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException waiting a message from the server!\n"+e.getStackTrace());
return;
} catch (IOException e) {
}
}
}
}
【问题讨论】:
标签: java multithreading sockets