CSFramework---最外层(Server/Client)的实现

C/S开发框架之最外层(服务器端和客户端)的实现

最外层是服务器端和客户端,也就是直接由使用C/S框架的用户使用的两个类。

客户端—Client类

与服务器端一样,先实现客户端最基本的功能:
1.连接服务器(若连接失败,则应告知APP层);
2.服务器异常宕机处理

连接服务器

连接服务器是客户端第一要务,如果服务器都没有连接上,那么,后续操作根本就谈不上了。

	public boolean connectToServer() throws ClientActionNotSetException {
		if (clientAction == null) {
			throw new ClientActionNotSetException("未设置Client Action!");
		}
		try {
			this.socket = new Socket(ip, me.getPort());
			this.clientConversation = new ClientConversation(this, socket);
		} catch (Exception e) {
			return false;
		}
		
		return true;
	}

通过返回值可以知道连接成功与否,这需要告知APP层,那么,APP如何知道呢?
而对于服务器端异常宕机的处理呢,我们知道,对于服务器异常宕机的识别,是在ClientConversation类中实现的,Client类得知服务器异常掉线的消息,作为工具是无法处理的,或者说,对于”服务器异常掉线“这种情况,我们只能告知APP层,由APP层具体处理。
那么,问题就是,如何告知APP层呢?
我们现在做的是工具,APP当然是未来使用这个工具的用户编写的,所以,我们可以提供一个接口,APP客户端必须实现这个接口,而Client类中将接口对象作为成员,这样就可以将App层的”网络响应“代码”装配“到Client中。

package com.mec.csframework.core;

public interface IClientAction {
	void serverOutOfRoom();
	void afterConnectToServer();
	boolean confirmOffline();
	void beforeOffline();
	void afterOffline();
	void serverAbnormalDrop();
	void serverForcedown();
	
	void dealToOne(String sourceId, String message);
	void dealToOther(String sourceId, String message);
}

我们可以看到,IClientAction接口中的方法都是需要用户具体去实现的方法。

同时提供一个接口的适配器ClientActionAdapter:

package com.mec.csframework.core;

public class ClientActionAdapter implements IClientAction {

	public ClientActionAdapter() {
	}
	
	@Override
	public void afterConnectToServer() {
	}

	@Override
	public void serverOutOfRoom() {
	}

	@Override
	public boolean confirmOffline() {
		return true;
	}

	@Override
	public void afterOffline() {
	}

	@Override
	public void serverAbnormalDrop() {
	}

	@Override
	public void dealToOne(String sourceId, String message) {
	}

	@Override
	public void dealToOther(String sourceId, String message) {
	}

	@Override
	public void serverForcedown() {
	}

	@Override
	public void beforeOffline() {
	}

}

这个适配器可以什么都不用做,相当于一个”空壳子“,因为具体实现工作是在APP层中具体实现的,APP层中可以以内部类继承于ClientActionAdapter的实现方式,也可以以匿名内部类的方式。
这里给一个内部类实现的例子:

	class connectToServer extends ClientActionAdapter {
		
		public connectToServer() {
		}

		@Override
		public void serverOutOfRoom() {
			ViewTool.showMessage(jfrmClientView, "服务器已满,请稍后尝试!");
			try {
				exitView();
			} catch (FramelsNullException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void afterConnectToServer() {
			ClientLogin clientLogin = new ClientLogin(client);
			try {
				clientLogin.showView();
			} catch (FramelsNullException e1) {
				e1.printStackTrace();
			}
			try {
				exitView();
			} catch (FramelsNullException e) {
				e.printStackTrace();
			}
			
		}
	}

同样,可以编写一个View界面简单测试一下服务器连接,当然这里为了简单起见,连接成功之后并没有执行上面代码的用户登录的操作,只是显示一下连接成功即可。下面是测试结果如下图:
在这里插入图片描述

Client类完整代码:

package com.mec.csframework.core;

import java.net.Socket;
import java.net.UnknownHostException;

import com.mec.csframework.action.DefaultActionProcessor;
import com.mec.csframework.action.IActionProcessor;
import com.mec.util.PropertiesParser;

public class Client {
	private String ip;
	private Socket socket;
	private ClientConversation clientConversation;
	private IClientAction clientAction;
	private NetNode me;
	
	private IActionProcessor actionProcessor;
	
	public Client() throws UnknownHostException {
		this.ip = INetBaseConfig.DEFAULT_IP;
		this.me = new NetNode().setPort(INetBaseConfig.DEFAULT_PORT);
		this.actionProcessor = new DefaultActionProcessor();
	}

	IClientAction getClientAction() {
		return clientAction;
	}
	
	NetNode getMe() {
		return me;
	}
	
	IActionProcessor getActionProcesser() {
		return this.actionProcessor;
	}
	
	public void initClient(String configPath) {
		PropertiesParser pp = new PropertiesParser();
		pp.loadProperties(configPath);

		String ip = pp.value("ip");
		if (ip != null && ip.length() > 0) {
			this.ip = ip;
		}
		
		String strPort = pp.value("port");
		if (strPort != null && strPort.length() > 0) {
			this.me.setPort(Integer.valueOf(strPort));
		}
	}
	
	public void initClient() {
		initClient("/net.cfg.properties");
	}
	
	public void sendMessageToServer(String message) {
		this.clientConversation.sendMessageToServer(message);
	}
	
	public void sendRequest(String action, String parameter) {
		this.clientConversation.sendRequest(action, action, parameter);
	}
	
	public void sendRequest(String request, String response, String parameter) {
		this.clientConversation.sendRequest(request, response, parameter);
	}
	
	public void setClientAction(IClientAction clientAction) {
		this.clientAction = clientAction;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	public void setPort(int port) {
		this.me.setPort(port);
	}
	
	public String getId() {
		return this.clientConversation.getId();
	}
	
	public void offline() {
		if (clientAction.confirmOffline()) {
			clientAction.beforeOffline();
			clientConversation.offline();
			clientAction.afterOffline();
		}
	}
	
	public boolean connectToServer() throws ClientActionNotSetException {
		if (clientAction == null) {
			throw new ClientActionNotSetException("未设置Client Action!");
		}
		try {
			this.socket = new Socket(ip, me.getPort());
			this.clientConversation = new ClientConversation(this, socket);
		} catch (Exception e) {
			return false;
		}
		
		return true;
	}
	
	public void toOne(String id, String message) {
		clientConversation.toOne(id, message);
	}
	
	public void toOther(String message) {
		clientConversation.toOther(message);
	}
	
}

至此,结合上篇文章,关于CSFramework的最外层,即Server和Client类的功能简述结束。

下一篇将继续CSFramework的另一核心部分,关于action和分发器的实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值