欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(JAVASE)CSFrameWork详解(Client及ClientConversation)

程序员文章站 2024-03-25 20:22:34
...

ClientConversation继承于communication,所以在该层就该将抽象方法具体实现,完善其对信息的具体操作。

client是提供给app层调用的类,其包含的方法都是发出请求,实际是调用了conversation里的方法通过communication向服务端发信息。

conversation层处理信息的发出和接受,发出是提供给client层并进一步给app层使用的,信息的接受就是完成dealNetMessage抽象方法的实现,对应不同的command调用适配器中的不同方法。

首先对于所有的客户端操作都先用接口表示一下:

void serverOutOfRoom();
	void afterConnectToServer();
	void serverAbnormalDrop();
	void toOne(String source, String message);
	void toOther(String source, String message);
	boolean confirmOffline();
	void beforeOffline();
	void afterOffline();
	void serverForceDown();
	void killByServer(String reason);
	
	void dealResponse(String action, String message);

分别是:
连接到服务器之后需要进行的操作;
对应服务端异常掉线的处理;
信息单发及群发;
确认当前是否离线;
离线前和离线后的操作;
服务器强制宕机后的处理;
被服务器强制下线的操作;
对服务器答复的处理。

但是对接口的直接使用,会将成堆未实现的方法一股脑放到程序中,而实际应用应该是对不同情景,取出对应的处理方法,这就引入适配器的使用。

适配器:

public class ClientActionAdapter implements IClientAction {

	public ClientActionAdapter() {
	}
	
	@Override
	public void serverOutOfRoom() {}
	@Override
	public void serverAbnormalDrop() {}
	@Override
	public void toOne(String source, String message) {}
	@Override
	public boolean confirmOffline() {
		return true;
	}
	@Override
	public void afterOffline() {}
	@Override
	public void beforeOffline() {}
	@Override
	public void toOther(String source, String message) {}
	@Override
	public void serverForcedown() {}
	@Override
	public void killByServer(String reason) {}
	@Override
	public void afterConnectToServer() {}
	@Override
	public void dealResponse(String action, String parameter) {}

}

实际适配器就是对接口的空实现,在后期使用方法:

private IClientAction clientAction;
this.clientAction = new ClientActionAdapter();

首先将该接口作为成员加入类中,接着用适配器将该成员实现。

this.client.getClientAction().serverOutOfRoom();

之后像上述使用。
注:主要用于接受信息后从适配器中提取需要的方法进行处理。

先完成ClientConversation中信息发出的函数及构造方法:

private Client client;
	private String id;

	public ClientConversation(Socket socket, Client client) throws IOException {
		super(socket);
		this.client = client;
	}

ClientConversation有两个成员,id的获取在连接到服务器之后由服务器发回。
其构造方法是沿用父类communication。

发送信息:

void sendRequest(String action, String parameter) {
		send(new NetMessage()
				.setCommand(ENetCommand.REQUEST)
				.setSource(id)
				.setTarget(Server.SERVER)
				.setAction(action)
				.setMessage(parameter));
	}
	void offline() {
		send(new NetMessage()
				.setCommand(ENetCommand.OFFLINE));
		close();
	}
	
	void toOne(String targetId, String message) {
		send(new NetMessage()
				.setCommand(ENetCommand.TO_ONE)
				.setSource(id)
				.setTarget(targetId)
				.setMessage(message));
	}
	
	void toOther(String message) {
		send(new NetMessage()
				.setCommand(ENetCommand.TO_OTHER)
				.setSource(id)
				.setTarget(Server.SERVER)
				.setMessage(message));
	}
	
	void messageToServer(String message) {
		send(new NetMessage()
				.setCommand(ENetCommand.MESSAGE_TO_SERVER)
				.setSource(id)
				.setTarget(Server.SERVER)
				.setMessage(message));
	}

对应枚举命令定义所需方法即可。

上述方法就是给Client调用的方法。
Client构造:

	private String ip;
	private int port;
	private Socket socket;
	private ClientConversation conversation;
	private IClientAction clientAction;
	private IRequestResponseAction responseAction;
	public static final Gson gson = new GsonBuilder().create();
	
	public Client() {
		this.ip = INetConfig.ip;
		this.port = INetConfig.port;
		this.clientAction = new ClientActionAdapter();
		this.responseAction = new RequestResponseAction();
	}

Client调用:

public void sendRequest(String action, String parameter) {
		this.conversation.sendRequest(action, parameter);
	}
	
	public void offline() {
		if (this.clientAction.confirmOffline()) {
			this.clientAction.beforeOffline();
			this.conversation.offline();
			this.clientAction.afterOffline();
		}
	}
	
	public void toOne(String targetId, String message) {
		this.conversation.toOne(targetId, message);
	}
	
	public void toOther(String message) {
		this.conversation.toOther(message);
	}
	
	public void messageToServer(String message) {
		this.conversation.messageToServer(message);
	}

连接服务器:

public boolean connectToServer() {
		try {
			this.socket = new Socket(this.ip, this.port);
			this.conversation = new ClientConversation(socket, this);
			return true;
		} catch (IOException e) {
		}
		return false;
	}

连接到服务器的操作就是依据当前配置文件的ip和端口,新建一个信息交互通道,并且将该通道和Client本身加到conversation中。

接收信息的反馈处理:

public void dealNetMessage(NetMessage netMessage) {
		ENetCommand command = netMessage.getCommand();
		switch (command) {
		case OUT_OF_ROOM:
			// 应该由APP层的客户端逻辑,处理OutofRoom!
			this.client.getClientAction().serverOutOfRoom();
			close();
			break;
		case ID:
			this.id = netMessage.getTarget();
			this.client.getClientAction().afterConnectToServer();
			break;
		case TO_ONE:
			// 客户端接收到服务器发送的另一个客户端的单聊信息,
			// 这个信息的处理应该由APP层决定,本工具没有处置权利!
			this.client.getClientAction().toOne(netMessage.getSource(), netMessage.getMessage());
			break;
		case TO_OTHER:
			this.client.getClientAction().toOther(netMessage.getSource(), netMessage.getMessage());
			break;
		case FORCEDOWN:
			this.client.getClientAction().serverForcedown();
			close();
			break;
		case KILL_CLIENT:
			this.client.getClientAction().killByServer(netMessage.getMessage());
			close();
			break;
		case RESPONSE:
			try {
				this.client.getResponseAction().dealResponse(
						netMessage.getAction(), netMessage.getMessage());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		default:
			break;
		}

这段就是根据客户端接收到的命令字段,判断对应的操作。
利用this.client.getResponseAction().调用对应方法。

相关标签: 实训