├── JServer ├── .idea │ ├── compiler.xml │ ├── copyright │ │ └── profiles_settings.xml │ ├── deployment.xml │ ├── description.html │ ├── encodings.xml │ ├── misc.xml │ ├── modules.xml │ ├── uiDesigner.xml │ ├── vcs.xml │ └── workspace.xml ├── MedServer.iml ├── README.txt ├── config │ └── log4j.properties ├── lib │ ├── log4j-1.2.16.jar │ ├── mybatis-3.1.1.jar │ ├── mysql-connector-java-5.0.8-bin.jar │ ├── netty-all-4.1.6.Final.jar │ └── protobuf-java-2.6.1.jar ├── res │ └── protocol │ │ ├── RM.BaseDefine.proto │ │ ├── RM.File.proto │ │ ├── RM.Login.proto │ │ └── RM.Message.proto └── src │ ├── Main.java │ ├── base │ ├── config │ │ ├── ConfigReader.java │ │ └── ConfigUtil.java │ ├── exception │ │ └── ConfigException.java │ ├── pdu │ │ ├── PduBase.java │ │ ├── PduDecoder.java │ │ ├── PduEncoder.java │ │ ├── PduHandler.java │ │ ├── PduHeader.java │ │ └── RMCommons.java │ └── protobuf │ │ ├── basedefine │ │ └── RMBaseDefine.java │ │ ├── file │ │ └── RMFile.java │ │ ├── login │ │ └── RMLogin.java │ │ └── message │ │ └── RMMessage.java │ ├── dbserver │ ├── DataBaseServer.java │ ├── DataBaseServer.properties │ ├── dao │ │ └── UserDao.java │ ├── dbconfig.properties │ ├── entity │ │ └── UserInfoVo.java │ ├── mapper │ │ └── UserMapper.xml │ └── mybatis-config.xml │ ├── fileserver │ ├── FileServer.java │ ├── FileServer.properties │ └── dfsserver │ │ ├── HISTORY │ │ ├── README │ │ ├── build.xml │ │ ├── fdfs_client.conf │ │ └── org │ │ └── csource │ │ ├── common │ │ ├── Base64.java │ │ ├── IniFileReader.java │ │ ├── MyException.java │ │ └── NameValuePair.java │ │ └── fastdfs │ │ ├── ClientGlobal.java │ │ ├── DownloadCallback.java │ │ ├── DownloadStream.java │ │ ├── FileInfo.java │ │ ├── ProtoCommon.java │ │ ├── ProtoStructDecoder.java │ │ ├── ServerInfo.java │ │ ├── StorageClient.java │ │ ├── StorageClient1.java │ │ ├── StorageServer.java │ │ ├── StructBase.java │ │ ├── StructGroupStat.java │ │ ├── StructStorageStat.java │ │ ├── TrackerClient.java │ │ ├── TrackerGroup.java │ │ ├── TrackerServer.java │ │ ├── UploadCallback.java │ │ ├── UploadStream.java │ │ └── test │ │ ├── DownloadFileWriter.java │ │ ├── Monitor.java │ │ ├── Test.java │ │ ├── Test1.java │ │ ├── TestAppender.java │ │ ├── TestAppender1.java │ │ ├── TestClient.java │ │ ├── TestClient1.java │ │ ├── TestLoad.java │ │ └── UploadLocalFileSender.java │ ├── loginserver │ ├── LoginServer.java │ ├── LoginServer.properties │ ├── conf │ │ ├── ClientType.java │ │ └── LoginMsgType.java │ ├── handler │ │ └── channel │ │ │ ├── CLoginInBaseHandler.java │ │ │ └── CLoginOutBaseHandler.java │ ├── test │ │ └── Test1.java │ └── vo │ │ └── MsgServerInfo.java │ ├── msgserver │ ├── MsgServer.java │ ├── MsgServer.properties │ ├── conf │ │ └── MsgPduType.java │ ├── global │ │ └── MsgGlobal.java │ └── handler │ │ └── channel │ │ ├── CMsgServerInBaseHandler.java │ │ └── CMsgServerOutBaseHandler.java │ └── sessionserver │ ├── SessionServer.java │ └── SessionServer.properties └── README.md /JServer/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /JServer/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /JServer/.idea/deployment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /JServer/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /JServer/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /JServer/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 24 | 26 | -------------------------------------------------------------------------------- /JServer/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JServer/.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /JServer/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /JServer/MedServer.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /JServer/README.txt: -------------------------------------------------------------------------------- 1 | 服务器 2 | -------------------------------------------------------------------------------- /JServer/config/log4j.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/config/log4j.properties -------------------------------------------------------------------------------- /JServer/lib/log4j-1.2.16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/lib/log4j-1.2.16.jar -------------------------------------------------------------------------------- /JServer/lib/mybatis-3.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/lib/mybatis-3.1.1.jar -------------------------------------------------------------------------------- /JServer/lib/mysql-connector-java-5.0.8-bin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/lib/mysql-connector-java-5.0.8-bin.jar -------------------------------------------------------------------------------- /JServer/lib/netty-all-4.1.6.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/lib/netty-all-4.1.6.Final.jar -------------------------------------------------------------------------------- /JServer/lib/protobuf-java-2.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/lib/protobuf-java-2.6.1.jar -------------------------------------------------------------------------------- /JServer/res/protocol/RM.BaseDefine.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/res/protocol/RM.BaseDefine.proto -------------------------------------------------------------------------------- /JServer/res/protocol/RM.File.proto: -------------------------------------------------------------------------------- 1 | package RM.File; 2 | import "RM.BaseDefine.proto"; 3 | option java_package = "base.protobuf.file"; 4 | //option java_outer_classname = "MOBILEMedical"; 5 | option optimize_for = LITE_RUNTIME; 6 | 7 | // 文件列表请求 8 | message IMFileListReq{ 9 | //cmd id: 0x0501 10 | required uint32 user_id = 1; 11 | } 12 | 13 | // 文件列表返回 14 | message IMFileListRsp{ 15 | //cmd id: 0x0502 16 | required uint32 result_code = 1; //0:successed 1:failed 17 | repeated RM.BaseDefine.HeartFileInfo file_list = 2; //所有文件列表信息 18 | } 19 | 20 | // 文件删除请求 21 | message IMFileDeleteReq{ 22 | //cmd id: 0x0503 23 | required uint32 user_id = 1; 24 | required uint32 file_id = 2; 25 | } 26 | 27 | // 文件删除返回 28 | message IMFileDeleteRsp{ 29 | //cmd id: 0x0504 30 | required uint32 user_id = 1; 31 | required uint32 result_code = 2; 32 | } 33 | 34 | 35 | // 文件上传请求 36 | message IMFileUploadReq{ 37 | //cmd id: 0x0505 38 | required uint32 user_id = 1; 39 | required RM.BaseDefine.FileInfo file_info = 2; 40 | required bytes file_data = 3; 41 | } 42 | 43 | // 文件上传返回 44 | message IMFileUploadRsp{ 45 | //cmd id: 0x0506 46 | required uint32 user_id = 1; 47 | required uint32 result_code = 2; 48 | } 49 | 50 | // 文件元信息保存请求 51 | message IMFileMetaDataSaveReq{ 52 | //cmd id: 0x0507 53 | required uint32 user_id = 1; 54 | required string store_url = 2; //文件存储的路径 55 | required RM.BaseDefine.FileInfo file_info = 3; 56 | } 57 | 58 | // 文件元信息保存返回 59 | message IMFileMetaDataSaveRsp{ 60 | //cmd id: 0x0508 61 | required uint32 user_id = 1; 62 | required uint32 result_code = 2; 63 | } 64 | 65 | // 文件下载请求 66 | message IMFileDownloadReq{ 67 | //cmd id: 0x0509 68 | required uint32 user_id = 1; 69 | required string store_url = 2; //文件存储的路径 70 | } 71 | 72 | // 文件下载返回 73 | message IMFileDownloadRsp{ 74 | //cmd id: 0x0510 75 | required uint32 user_id = 1; 76 | required bytes file_data = 2; 77 | } -------------------------------------------------------------------------------- /JServer/res/protocol/RM.Login.proto: -------------------------------------------------------------------------------- 1 | package RM.Login; 2 | import "RM.BaseDefine.proto"; 3 | option java_package = "base.protobuf.login"; 4 | //option java_outer_classname = "MOBILEMedical"; 5 | option optimize_for = LITE_RUNTIME; 6 | 7 | //service id: 0x0001 8 | 9 | // msg_server地址请求(已经废弃,改用http请求) 10 | message IMMsgServReq{ 11 | //cmd id: 0x0101 12 | } 13 | // msg_server地址应答(已经废弃) 14 | message IMMsgServRsp{ 15 | //cmd id: 0x0102 16 | required RM.BaseDefine.ResultType result_code = 1; 17 | optional string prior_ip = 2; 18 | optional string backip_ip = 3; 19 | optional uint32 port = 4; 20 | } 21 | 22 | // 登录请求 23 | message IMLoginReq{ 24 | //cmd id: 0x0103 25 | required string user_name = 1; 26 | required string password = 2; 27 | required RM.BaseDefine.UserStatType online_status = 3; 28 | required RM.BaseDefine.ClientType client_type = 4; 29 | optional string client_version = 5; 30 | } 31 | 32 | // 登录返回 33 | message IMLoginRes{ 34 | //cmd id: 0x0104 35 | required uint32 server_time = 1; 36 | required RM.BaseDefine.ResultType result_code = 2; 37 | optional string result_string = 3; 38 | optional RM.BaseDefine.UserStatType online_status = 4; 39 | optional RM.BaseDefine.UserInfo user_info = 5; 40 | } 41 | 42 | // 登出请求 43 | message IMLogoutReq{ 44 | //cmd id: 0x0105 45 | } 46 | 47 | // 登出返回 48 | message IMLogoutRsp{ 49 | //cmd id: 0x0106 50 | required uint32 result_code = 1; 51 | } -------------------------------------------------------------------------------- /JServer/res/protocol/RM.Message.proto: -------------------------------------------------------------------------------- 1 | package RM.Message; 2 | import "RM.BaseDefine.proto"; 3 | option java_package = "base.protobuf.message"; 4 | //option java_outer_classname = "MOBILEMedical"; 5 | option optimize_for = LITE_RUNTIME; 6 | 7 | //service id 0x0003 8 | 9 | // 发送消息协议。 10 | message IMMsgData{ 11 | //cmd id: 0x0301 12 | required uint32 from_user_id = 1; //消息发送方 13 | required uint32 to_session_id = 2; //消息接受方 14 | required uint32 msg_id = 3; 15 | required uint32 create_time = 4; 16 | required RM.BaseDefine.MsgType msg_type = 5; 17 | required bytes msg_data = 6; 18 | optional bytes attach_data = 20; 19 | } 20 | 21 | // 消息收到回复。 22 | message IMMsgDataAck{ 23 | //cmd id: 0x0302 24 | required uint32 user_id = 1; //发送此信令的用户id 25 | required uint32 session_id = 2; 26 | required uint32 msg_id = 3; 27 | required RM.BaseDefine.SessionType session_type = 4; 28 | } 29 | 30 | // 消息已读回复。 31 | message IMMsgDataReadAck{ 32 | //cmd id: 0x0303 33 | required uint32 user_id = 1; //发送此信令的用户id 34 | required uint32 session_id = 2; 35 | required uint32 msg_id = 3; 36 | required RM.BaseDefine.SessionType session_type = 4; 37 | } -------------------------------------------------------------------------------- /JServer/src/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | 3 | public static void main(String[] args) { 4 | System.out.println("Hello World!"); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /JServer/src/base/config/ConfigReader.java: -------------------------------------------------------------------------------- 1 | package base.config; 2 | 3 | import base.exception.ConfigException; 4 | import org.apache.log4j.Logger; 5 | 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.util.*; 10 | 11 | /** 12 | * Created by Administrator on 2017/5/15 0015. 13 | */ 14 | public class ConfigReader { 15 | private Map configMap = new HashMap<>(); 16 | private static Logger logger = Logger.getLogger(ConfigReader.class); 17 | 18 | public ConfigReader(String filePath){ 19 | if(filePath != null){ 20 | logger.debug("正在解析配置文件:"+filePath); 21 | this.read(filePath); 22 | } 23 | } 24 | 25 | public boolean read(String propFile) { 26 | Properties props = new Properties(); 27 | InputStream in = null; 28 | try { 29 | in = new FileInputStream(propFile); 30 | if (in != null) { 31 | props.load(in); 32 | }else{ 33 | logger.error("加载配置文件错误"); 34 | return false; 35 | } 36 | // 解析properties文件 37 | Set> set = props.entrySet(); 38 | Iterator> it = set.iterator(); 39 | while (it.hasNext()) { 40 | Map.Entry entry = it.next(); 41 | String key = entry.getKey().toString(); 42 | String value = entry.getValue().toString(); 43 | String fuKey = getWildcard(value); 44 | 45 | if(null != fuKey && null != props.get(fuKey)){ 46 | String fuValue = props.get(fuKey).toString(); 47 | value = value.replaceAll("\\$\\{" + fuKey + "\\}", fuValue); 48 | } 49 | configMap.put(key, value); 50 | } 51 | return true; 52 | } catch (IOException e) { 53 | throw new ConfigException("load properties file error!"); 54 | } finally { 55 | if(in != null){ 56 | try{ 57 | in.close(); 58 | }catch (IOException e){ 59 | e.printStackTrace(); 60 | } 61 | } 62 | } 63 | } 64 | 65 | private String getWildcard(String str){ 66 | if(null != str && str.indexOf("${") != -1){ 67 | int start = str.indexOf("${"); 68 | int end = str.indexOf("}"); 69 | if(start != -1 && end != -1){ 70 | return str.substring(start + 2, end); 71 | } 72 | } 73 | return null; 74 | } 75 | 76 | public String getString(String key) { 77 | Object object = configMap.get(key); 78 | if(null != object){ 79 | return object.toString(); 80 | } 81 | return null; 82 | } 83 | 84 | public Integer getInt(String key) { 85 | String value = this.getString(key); 86 | if(null != value){ 87 | return Integer.parseInt(value); 88 | } 89 | return null; 90 | } 91 | 92 | public Long getLong(String key) { 93 | String value = this.getString(key); 94 | if(null != value){ 95 | return Long.parseLong(value); 96 | } 97 | return null; 98 | } 99 | 100 | public Boolean getBoolean(String key) { 101 | String value = this.getString(key); 102 | if(null != value){ 103 | return Boolean.parseBoolean(value); 104 | } 105 | return null; 106 | } 107 | 108 | public Double getDouble(String key) { 109 | String value = this.getString(key); 110 | if(null != value){ 111 | return Double.parseDouble(value); 112 | } 113 | return null; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /JServer/src/base/config/ConfigUtil.java: -------------------------------------------------------------------------------- 1 | package base.config; 2 | 3 | public class ConfigUtil { 4 | public static String getAbsolateConfPath(String relativePath, String configFileName){ 5 | String projectPath = System.getProperty("user.dir"); 6 | 7 | StringBuilder stringBuilder = new StringBuilder(); 8 | stringBuilder.append(projectPath); 9 | stringBuilder.append(relativePath); 10 | stringBuilder.append(configFileName); 11 | 12 | return stringBuilder.toString(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /JServer/src/base/exception/ConfigException.java: -------------------------------------------------------------------------------- 1 | package base.exception; 2 | 3 | /** 4 | * 配置适配异常 5 | */ 6 | public class ConfigException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = 6118361499832602075L; 9 | 10 | public ConfigException(String msg){ 11 | super(msg); 12 | } 13 | 14 | public ConfigException(Throwable t){ 15 | super(t); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /JServer/src/base/pdu/PduBase.java: -------------------------------------------------------------------------------- 1 | package base.pdu; 2 | 3 | 4 | import io.netty.channel.Channel; 5 | 6 | import java.nio.ByteBuffer; 7 | 8 | /** 9 | * 通信包在业务层的表示 10 | * Created by Administrator on 2016/12/8 0008. 11 | */ 12 | public class PduBase { 13 | private Channel channel; // 包来自的socket管道(引用) 14 | private PduHeader header; // 包的头部 15 | private byte[] bodyArray; // 包体的字节流 16 | private int bodyOffset; 17 | private int bodyLen = 0; 18 | 19 | public PduHeader getHeader() { 20 | return header; 21 | } 22 | 23 | public void setHeader(PduHeader header) { 24 | this.header = header; 25 | 26 | } 27 | 28 | public byte[] getBodyArray() { 29 | return bodyArray; 30 | } 31 | 32 | public void setBodyArray(byte[] bodyArray) { 33 | 34 | this.bodyArray = bodyArray; 35 | } 36 | 37 | public int getBodyOffset() { 38 | return bodyOffset; 39 | } 40 | 41 | public void setBodyOffset(int bodyOffset) { 42 | this.bodyOffset = bodyOffset; 43 | } 44 | 45 | public int getBodyLen() { 46 | return bodyLen; 47 | } 48 | 49 | public void setBodyLen(int bodyLen) { 50 | this.bodyLen = bodyLen; 51 | } 52 | 53 | public Channel getChannel() { 54 | return channel; 55 | } 56 | 57 | public void setChannel(Channel channel) { 58 | this.channel = channel; 59 | } 60 | 61 | /** 62 | * 封装整个包到byte数组 63 | * @return 64 | */ 65 | public byte[] getByteArray(){ 66 | if((this.header != null)){ 67 | // 计算整个包长度 68 | int bodyLen = 0; 69 | if(this.bodyArray != null){ 70 | bodyLen = bodyArray.length; 71 | } 72 | int pduLen = RMCommons.PDU_HEADER_LEN + bodyLen; 73 | // 把包封装成为字节流 74 | ByteBuffer byteBuffer = ByteBuffer.allocate(pduLen); 75 | byteBuffer.putInt(header.getLength()); 76 | byteBuffer.putShort(header.getVersion()); 77 | byteBuffer.putShort(header.getFlag()); 78 | byteBuffer.putShort(header.getServiceId()); 79 | byteBuffer.putShort(header.getCommandId()); 80 | byteBuffer.putShort(header.getSeNum()); 81 | byteBuffer.putShort(header.getReserved()); 82 | if(this.bodyArray != null){ 83 | byteBuffer.put(bodyArray); 84 | } 85 | return byteBuffer.array(); 86 | } 87 | return null; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /JServer/src/base/pdu/PduDecoder.java: -------------------------------------------------------------------------------- 1 | package base.pdu; 2 | 3 | 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.Channel; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.ByteToMessageDecoder; 8 | import org.apache.log4j.Logger; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * 将字节流按照包的大小进行划分,并进行封装成PduBase包 14 | * 并通过netty处理管道传递给下一个管道处理程序 15 | * @see PduBase 16 | * Created by Administrator on 2016/12/8 0008. 17 | */ 18 | public class PduDecoder extends ByteToMessageDecoder { 19 | 20 | private static Logger logger = Logger.getLogger(PduDecoder.class); 21 | 22 | public PduDecoder(){ 23 | 24 | } 25 | @Override 26 | protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { 27 | int bufferLen = byteBuf.readableBytes(); 28 | logger.debug("处理客户端请求的......"+bufferLen+",rederIndex:"+byteBuf.readerIndex()); 29 | while(byteBuf.readableBytes() >= RMCommons.PDU_HEADER_LEN){ //判定byteBuf中是否包含完整包头 30 | byteBuf.markReaderIndex(); // 标记起始位置 31 | bufferLen = byteBuf.readableBytes(); 32 | int pduLen = byteBuf.readInt(); 33 | logger.debug("====处理客户端请求的......"+bufferLen+",rederIndex:"+byteBuf.readerIndex()+","+pduLen); 34 | if(bufferLen < pduLen ){ 35 | byteBuf.resetReaderIndex(); // 如果当前的bytebuf的大小没有包含一个完成的数据包,那么再重新读取 36 | return; 37 | } 38 | PduHeader header = new PduHeader(); 39 | header.setLength(pduLen); 40 | fillHeader(header, byteBuf); 41 | logger.debug("客户端请求的类型:"+header.getCommandId()); 42 | 43 | PduBase pduBase = new PduBase(); 44 | pduBase.setChannel(channelHandlerContext.channel()); 45 | pduBase.setHeader(header); 46 | if((pduLen - RMCommons.PDU_HEADER_LEN) > 0) { 47 | fillBody(pduBase, byteBuf, pduLen - RMCommons.PDU_HEADER_LEN, channelHandlerContext.channel()); 48 | list.add(pduBase); 49 | }else if((pduLen - RMCommons.PDU_HEADER_LEN) == 0){ 50 | list.add(pduBase); 51 | } 52 | } 53 | } 54 | 55 | /** 56 | * 填充包头的数据 57 | * @param header 58 | * @param byteBuf 59 | */ 60 | private void fillHeader(PduHeader header, ByteBuf byteBuf){ 61 | header.setVersion(byteBuf.readShort()); 62 | header.setFlag(byteBuf.readShort()); 63 | header.setServiceId(byteBuf.readShort()); 64 | header.setCommandId(byteBuf.readShort()); 65 | header.setSeNum(byteBuf.readShort()); 66 | header.setReserved(byteBuf.readShort()); 67 | } 68 | 69 | /** 70 | * 从netty的字节流中读取包体的字节并加入到PduBase中 71 | * @param pduBase 72 | * @param byteBuf 73 | * @param bodyLen 74 | * @param channel 75 | */ 76 | private void fillBody(PduBase pduBase, ByteBuf byteBuf, int bodyLen, Channel channel){ 77 | ByteBuf bodyBuffer = byteBuf.readBytes(bodyLen); // 读取body到buffer 78 | byte bodyArray[]; 79 | int offset = 0; // 暂时未用 80 | int bufferLen = bodyBuffer.readableBytes(); 81 | bodyArray = new byte[bufferLen]; 82 | bodyBuffer.readBytes(bodyArray, bodyBuffer.readerIndex(), bufferLen); 83 | // 填充pdu的body 84 | pduBase.setBodyArray(bodyArray); 85 | pduBase.setBodyLen(bufferLen); 86 | pduBase.setBodyOffset(offset); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /JServer/src/base/pdu/PduEncoder.java: -------------------------------------------------------------------------------- 1 | package base.pdu; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToByteEncoder; 6 | import org.apache.log4j.Logger; 7 | 8 | /** 9 | * Created by Administrator on 2016/12/8 0008. 10 | */ 11 | public class PduEncoder extends MessageToByteEncoder { 12 | private static Logger logger = Logger.getLogger(PduEncoder.class); 13 | @Override 14 | protected void encode(ChannelHandlerContext channelHandlerContext, PduBase rmPduBase, ByteBuf byteBuf) throws Exception { 15 | PduHeader header = rmPduBase.getHeader(); 16 | logger.debug("正在编码消息,消息类型:"+header.getCommandId()); 17 | byteBuf.writeBytes(rmPduBase.getByteArray()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /JServer/src/base/pdu/PduHandler.java: -------------------------------------------------------------------------------- 1 | package base.pdu; 2 | 3 | /** 4 | * 所有包的对应的handler的父类 5 | * Created by Administrator on 2016/12/8 0008. 6 | */ 7 | public class PduHandler { 8 | 9 | public void handlePdu(PduBase pduBase){ 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /JServer/src/base/pdu/PduHeader.java: -------------------------------------------------------------------------------- 1 | package base.pdu; 2 | 3 | /** 4 | * 包头的信息 5 | * Created by Administrator on 2016/12/8 0008. 6 | */ 7 | public class PduHeader implements Cloneable { 8 | 9 | private int length; // 整个包的长度(包头包体) 10 | private short version = 0; // 包的版本号 11 | private short flag = 0; // 12 | private short serviceId = 0; 13 | private short commandId = 0; // 包体类型 14 | private short seNum = 0; // 序列号 15 | private short reserved = 0; 16 | 17 | public int getLength() { 18 | return length; 19 | } 20 | 21 | public void setLength(int length) { 22 | this.length = length; 23 | } 24 | 25 | public short getVersion() { 26 | return version; 27 | } 28 | 29 | public void setVersion(short version) { 30 | this.version = version; 31 | } 32 | 33 | public short getFlag() { 34 | return flag; 35 | } 36 | 37 | public void setFlag(short flag) { 38 | this.flag = flag; 39 | } 40 | 41 | public short getServiceId() { 42 | return serviceId; 43 | } 44 | 45 | public void setServiceId(short serviceId) { 46 | this.serviceId = serviceId; 47 | } 48 | 49 | public short getCommandId() { 50 | return commandId; 51 | } 52 | 53 | public void setCommandId(short commandId) { 54 | this.commandId = commandId; 55 | } 56 | 57 | public short getSeNum() { 58 | return seNum; 59 | } 60 | 61 | public void setSeNum(short seNum) { 62 | this.seNum = seNum; 63 | } 64 | 65 | public short getReserved() { 66 | return reserved; 67 | } 68 | 69 | public void setReserved(short reserved) { 70 | this.reserved = reserved; 71 | } 72 | 73 | @Override 74 | protected PduHeader clone() throws CloneNotSupportedException { 75 | return (PduHeader)super.clone(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /JServer/src/base/pdu/RMCommons.java: -------------------------------------------------------------------------------- 1 | package base.pdu; 2 | 3 | /** 4 | * Created by Administrator on 2016/12/8 0008. 5 | */ 6 | public class RMCommons { 7 | // 包头大小 8 | public static int PDU_HEADER_LEN = 16; 9 | } 10 | -------------------------------------------------------------------------------- /JServer/src/dbserver/DataBaseServer.java: -------------------------------------------------------------------------------- 1 | package dbserver; 2 | 3 | import base.config.ConfigReader; 4 | import base.config.ConfigUtil; 5 | import dbserver.dao.UserDao; 6 | import dbserver.entity.UserInfoVo; 7 | import loginserver.LoginServer; 8 | import org.apache.ibatis.io.Resources; 9 | import org.apache.ibatis.session.SqlSession; 10 | import org.apache.ibatis.session.SqlSessionFactory; 11 | import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 | import org.apache.log4j.Logger; 13 | import org.apache.log4j.PropertyConfigurator; 14 | 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | 18 | /** 19 | * Created by Administrator on 2017/5/15 0015. 20 | */ 21 | public class DataBaseServer { 22 | 23 | public SqlSessionFactory sqlSessionFactory = null; 24 | private static Logger logger = Logger.getLogger(DataBaseServer.class); 25 | 26 | public DataBaseServer() { 27 | initLog(); 28 | initSqlSessionFactory(); 29 | } 30 | 31 | private void initSqlSessionFactory() { 32 | String resource = "dbserver/mybatis-config.xml"; 33 | InputStream inputStream = null; 34 | try { 35 | inputStream = Resources.getResourceAsStream(resource); 36 | sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | private void initLog(){ 43 | PropertyConfigurator.configure("config/log4j.properties"); 44 | } 45 | 46 | public static void main(String[] args) throws Exception { 47 | DataBaseServer dataBaseServer = new DataBaseServer(); 48 | SqlSession session = dataBaseServer.sqlSessionFactory.openSession(); 49 | try { 50 | // 获取数据库的dao实例 51 | UserDao userDao = session.getMapper(UserDao.class); 52 | UserInfoVo userInfoVo = (UserInfoVo) userDao.find("小米"); 53 | logger.debug("数据库的用户信息:"+userInfoVo.getUsername()+","+userInfoVo.getRealname()); 54 | } finally { 55 | session.close(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /JServer/src/dbserver/DataBaseServer.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mh47838704/IMJavaSparrow/f7e8d970af2996eb95f0ccdb819437242ef70f8c/JServer/src/dbserver/DataBaseServer.properties -------------------------------------------------------------------------------- /JServer/src/dbserver/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package dbserver.dao; 2 | 3 | import dbserver.entity.UserInfoVo; 4 | 5 | /** 6 | * 7 | */ 8 | public interface UserDao { 9 | public UserInfoVo find(String username); 10 | } 11 | -------------------------------------------------------------------------------- /JServer/src/dbserver/dbconfig.properties: -------------------------------------------------------------------------------- 1 | driver=com.mysql.jdbc.Driver 2 | url=jdbc:mysql://192.168.1.190:3306/medical?useUnicode=true&characterEncoding=UTF-8 3 | username=medical 4 | password=medical123456 -------------------------------------------------------------------------------- /JServer/src/dbserver/entity/UserInfoVo.java: -------------------------------------------------------------------------------- 1 | package dbserver.entity; 2 | 3 | public class UserInfoVo { 4 | 5 | private String username; 6 | private String realname; 7 | private String uphonenumber; 8 | 9 | public String getUsername() { 10 | return username; 11 | } 12 | public void setUsername(String username) { 13 | this.username = username; 14 | } 15 | public String getRealname() { 16 | return realname; 17 | } 18 | public void setRealname(String realname) { 19 | this.realname = realname; 20 | } 21 | public String getUphonenumber() { 22 | return uphonenumber; 23 | } 24 | public void setUphonenumber(String uphonenumber) { 25 | this.uphonenumber = uphonenumber; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /JServer/src/dbserver/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /JServer/src/dbserver/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /JServer/src/fileserver/FileServer.java: -------------------------------------------------------------------------------- 1 | package fileserver; 2 | 3 | import base.config.ConfigReader; 4 | import base.config.ConfigUtil; 5 | import base.pdu.PduDecoder; 6 | import base.pdu.PduEncoder; 7 | import base.pdu.PduHandler; 8 | import io.netty.bootstrap.ServerBootstrap; 9 | import io.netty.channel.ChannelFuture; 10 | import io.netty.channel.ChannelInitializer; 11 | import io.netty.channel.ChannelOption; 12 | import io.netty.channel.EventLoopGroup; 13 | import io.netty.channel.nio.NioEventLoopGroup; 14 | import io.netty.channel.socket.SocketChannel; 15 | import io.netty.channel.socket.nio.NioServerSocketChannel; 16 | import io.netty.handler.logging.LogLevel; 17 | import io.netty.handler.logging.LoggingHandler; 18 | import loginserver.LoginServer; 19 | import org.apache.log4j.Logger; 20 | import org.apache.log4j.PropertyConfigurator; 21 | 22 | import java.util.HashMap; 23 | 24 | /** 25 | * Created by Administrator on 2017/5/15 0015. 26 | */ 27 | public class FileServer { 28 | private HashMap handlerHashMap = new HashMap<>(); 29 | private static Logger logger = Logger.getLogger(LoginServer.class); 30 | public FileServer(){ 31 | initHandlerMap(this.handlerHashMap); 32 | initLog(); 33 | } 34 | public void bind(int clientListenPort) throws Exception { 35 | logger.debug("负载均衡服务器:启动客户端监听,端口号:"+clientListenPort); 36 | // 配置服务端的NIO线程组 37 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 38 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 39 | try { 40 | ServerBootstrap bootstrap = new ServerBootstrap(); 41 | bootstrap.group(bossGroup, workerGroup) 42 | .channel(NioServerSocketChannel.class) 43 | .option(ChannelOption.SO_BACKLOG, 100) 44 | .handler(new LoggingHandler(LogLevel.INFO)) 45 | .childHandler(new ChannelInitializer() { 46 | @Override 47 | public void initChannel(SocketChannel ch) { 48 | // 注册相应的handler和encoder和decoder 49 | ch.pipeline().addLast(new PduDecoder()); 50 | ch.pipeline().addLast(new PduEncoder()); 51 | // 添加file相关的handler 52 | } 53 | }); 54 | 55 | // 绑定端口,同步等待成功 56 | ChannelFuture f = bootstrap.bind(clientListenPort).sync(); 57 | // 等待服务端监听端口关闭 58 | f.channel().closeFuture().sync(); 59 | } finally { 60 | // 优雅退出,释放线程池资源 61 | bossGroup.shutdownGracefully(); 62 | workerGroup.shutdownGracefully(); 63 | } 64 | } 65 | 66 | /** 67 | * 初始化业务handlerMap 68 | * @return 69 | */ 70 | private HashMap initHandlerMap(HashMap handlerHashMap){ 71 | 72 | return handlerHashMap; 73 | } 74 | 75 | private void initLog(){ 76 | PropertyConfigurator.configure("config/log4j.properties"); 77 | } 78 | 79 | public static void main(String[] args) throws Exception { 80 | // 用于监听客户端的端口,从配置文件中读取(10010是默认值) 81 | int clientListenPort = 10010; 82 | // 配置文件名字 83 | String fileName = "FileServer.properties"; 84 | /* 解析配置文件 */ 85 | String relativePath = "\\src\\fileserver\\"; 86 | String fullPath = ConfigUtil.getAbsolateConfPath(relativePath, fileName); 87 | ConfigReader configReader = new ConfigReader(fullPath); 88 | // 获取配置文件中的端口号 89 | clientListenPort = configReader.getInt("ClientListenPort"); 90 | /* 初始化LoginServer服务器*/ 91 | LoginServer server = new LoginServer(); 92 | server.bind(clientListenPort); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /JServer/src/fileserver/FileServer.properties: -------------------------------------------------------------------------------- 1 | #Address=0.0.0.0 # address for client 2 | ClientListenIP=0.0.0.0 3 | ClientListenPort=8600 4 | 5 | SessionServerIP=127.0.0.1 6 | SessionServerPort=8200 7 | 8 | DataBaseServerIP=127.0.0.1 9 | DataBaseServerPort=10600 10 | 11 | TaskTimeout=60 12 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/HISTORY: -------------------------------------------------------------------------------- 1 | 2 | Version 1.26 2017-04-17 3 | * IniFileReader use getResourceAsStream first 4 | * change charactor encoding to UTF-8 5 | 6 | Version 1.25 2014-12-07 7 | * support connection stats since FastDFS Server v5.04 8 | 9 | Version 1.24 2012-12-01 10 | * bug fixed: StorageClient.get_file_info support appender file and 11 | slave file correctly 12 | 13 | Version 1.23 2012-11-18 14 | * query_file_info changed, you must 15 | upgrade your FastDFS server to V4.03 or higher version 16 | 17 | Version 1.22 2012-10-06 18 | * group and storage stat both add 1 field, you must 19 | upgrade your FastDFS server to V4.00 or higher version 20 | 21 | Version 1.21 2012-06-25 22 | * add exception class MyException 23 | * class IniFileReader same as FastDHT java client 24 | 25 | Version 1.20 2012-05-27 26 | * appender file support truncate and modify operation 27 | * storage stat add 6 fields, you must upgrade your 28 | FastDFS server to V3.08 or higher version 29 | 30 | Version 1.19 2011-05-29 31 | * storage stat add field if_trunk_server, you must upgrade your 32 | FastDFS server to V3.00 or higher version 33 | * tracker or storage close no throw IOException (silence close) 34 | 35 | Version 1.18 2011-01-29 36 | * storage stat support total_upload_bytes, success_upload_bytes, 37 | total_download_bytes and success_download_bytes etc. 18 fields 38 | you must upgrade your FastDFS server to V2.08 or higher version 39 | * StorageClient add functions: get_file_info and query_file_info, 40 | StorageClient1 add functions: get_file_info1 and query_file_info1 41 | 42 | Version 1.17 2011-01-09 43 | * slave file's prefix name can be empty, 44 | you must upgrade your FastDFS server to V2.07 or higher version 45 | * support list group stats and storage stats 46 | * support delete storage server 47 | * add monitor class: org.csource.fastdfs.test.Monitor 48 | 49 | Version 1.16 2010-10-17 50 | * upload file can get available storage server list of the group, 51 | you must upgrade your FastDFS server to V2.01 or higher version 52 | 53 | Version 1.15 2010-08-07 54 | * protocol reponse command changed. you must upgrade your FastDFS server 55 | to V2.00 or higher version 56 | * upload file protocol changed, you must upgrade your FastDFS server 57 | to V2.00 or higher version 58 | 59 | Version 1.14 2010-06-22 60 | * bug fixed: delete the new created local file when download_file to 61 | local file fail 62 | * support connect timeout for connecting, the network timeout used to 63 | read and write 64 | 65 | Version 1.13 2010-05-30 66 | * org.csource.fastdfs.ProtoCommon add method genSlaveFilename 67 | * support ACTIVE_TEST command. you must upgrade your FastDFS server 68 | to V1.28 or higher version 69 | 70 | Version 1.12 2009-11-27 71 | * support uploading slave file 72 | * file ext name change from 5 to 6, you must upgrade your FastDFS server 73 | to V1.23 or higher version 74 | 75 | Version 1.11 2009-10-22 76 | * correct interface / class name from beginning with Dowload to Download 77 | * auto reconnect with reused connection when IOException ocurs 78 | * test classes move to package org.csource.fastdfs.test 79 | * add classes org.csource.fastdfs.UploadStream and 80 | org.csource.fastdfs.DownloadStream for streaming writing or reading 81 | 82 | Version 1.10 2009-10-04 83 | * support multi-tracker server group, you can make multi 84 | org.csource.fastdfs.TrackerClient instances for each tracker server group 85 | 86 | Version 1.9 2009-10-01 87 | * add load test class: org.csource.fastdfs.TestLoad 88 | * network IO performance enhancement 89 | * upload file support callback for sending file content 90 | 91 | Version 1.8 2009-08-30 92 | * TrackerClient, in function getConnection, add synchronized to avoid conflict 93 | * support file URL with token 94 | 95 | Version 1.7 2009-08-01 96 | * support cmd TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL: query all storage 97 | servers, you must upgrade your FastDFS server to V1.19 or higher version 98 | 99 | Version 1.6 2009-05-24 100 | * download file support offset and download bytes, you must upgrade your 101 | FastDFS server to V1.18 or higher version 102 | 103 | Version 1.5 2009-02-14 104 | * client can specify group name when upload file, you must upgrade your 105 | FastDFS server to V1.16 or higher version 106 | 107 | Version 1.4 2008-11-10 108 | * upload file support ext name, you must upgrade your 109 | FastDFS server to V1.12 or higher version 110 | * upload protocol add field store_path_index (1 byte) 111 | * add method TrackerClient.getUpdateStorage. to support getmeta, setmeta 112 | and delete file 113 | * TrackerClient.getFetchStorage bug fixed 114 | 115 | Version 1.3 2008-10-16 116 | * client download file support callback function(class) 117 | * add class "StorageClient1" and function "TrackerClient.getFetchStorage1" 118 | to combine 2 fields: group name and filename to 1 field: file id 119 | * add anothor client test program: TestClient1.java to use file id 120 | 121 | Version 1.2 2008-09-08 122 | * communication protocol changed to support large file exceed 2GB: 123 | all integer field is 8 bytes big-endian, 124 | you must upgrade your FastDFS server to V1.8 or higher version 125 | 126 | Version 1.1 2008-08-10 127 | * upload file package remove the one pad byte field, you must upgrade your 128 | FastDFS server to V1.4 or higher version 129 | 130 | Version 1.0 2008-08-03 131 | * first version 132 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/README: -------------------------------------------------------------------------------- 1 | Copyright (C) 2008 Happy Fish / YuQing 2 | 3 | FastDFS Java Client API may be copied only under the terms of 4 | the BSD license. 5 | Please visit the FastDFS Home Page for more detail. 6 | English language: http://english.csource.org/ 7 | Chinese language: http://www.csource.org/ 8 | 9 | 10 | The jar file is compiled by JDK1.5, you can download the last version 11 | from google code: http://code.google.com/p/fastdfs/downloads/list 12 | 13 | run the FastDFS Java Client test: 14 | java -cp org.csource.fastdfs.test.TestClient 15 | 16 | eg.: 17 | java -cp fastdfs_client_v1.25.jar org.csource.fastdfs.test.TestClient fdfs_client.conf c:\windows\system32\notepad.exe 18 | 19 | or: 20 | java -cp fastdfs_client_v1.25.jar org.csource.fastdfs.test.TestClient fdfs_client.conf /usr/include/stdlib.h 21 | 22 | 23 | run the FastDFS monitor: 24 | java -cp org.csource.fastdfs.test.Monitor 25 | 26 | eg.: 27 | java -cp fastdfs_client_v1.25.jar org.csource.fastdfs.test.Monitor fdfs_client.conf 28 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/fdfs_client.conf: -------------------------------------------------------------------------------- 1 | connect_timeout = 2 2 | network_timeout = 30 3 | charset = UTF-8 4 | http.tracker_http_port = 8080 5 | http.anti_steal_token = no 6 | http.secret_key = FastDFS1234567890 7 | 8 | tracker_server = 192.168.1.190:22122 9 | tracker_server = 192.168.1.190:22122 10 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/common/Base64.java: -------------------------------------------------------------------------------- 1 | package fileserver.dfsserver.org.csource.common; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Freeware from: 7 | * Roedy Green 8 | * Canadian Mind Products 9 | * #327 - 964 Heywood Avenue 10 | * Victoria, BC Canada V8V 2Y5 11 | * tel:(250) 361-9093 12 | * mailto:roedy@mindprod.com 13 | */ 14 | 15 | /** 16 | * Encode arbitrary binary into printable ASCII using BASE64 encoding. 17 | * very loosely based on the Base64 Reader by 18 | * Dr. Mark Thornton 19 | * Optrak Distribution Software Ltd. 20 | * http://www.optrak.co.uk 21 | * and Kevin Kelley's http://www.ruralnet.net/~kelley/java/Base64.java 22 | * 23 | * Base64 is a way of encoding 8-bit characters using only ASCII printable 24 | * characters similar to UUENCODE. UUENCODE includes a filename where BASE64 does not. 25 | * The spec is described in RFC 2045. Base64 is a scheme where 26 | * 3 bytes are concatenated, then split to form 4 groups of 6-bits each; and 27 | * each 6-bits gets translated to an encoded printable ASCII character, via a 28 | * table lookup. An encoded string is therefore longer than the original by 29 | * about 1/3. The "=" character is used to pad the end. Base64 is used, 30 | * among other things, to encode the user:password string in an 31 | * Authorization: header for HTTP. Don't confuse Base64 with 32 | * x-www-form-urlencoded which is handled by 33 | * Java.net.URLEncoder.encode/decode 34 | * If you don't like this code, there is another implementation at http://www.ruffboy.com/download.htm 35 | * Sun has an undocumented method called sun.misc.Base64Encoder.encode. 36 | * You could use hex, simpler to code, but not as compact. 37 | * 38 | * If you wanted to encode a giant file, you could do it in large chunks that 39 | * are even multiples of 3 bytes, except for the last chunk, and append the outputs. 40 | * 41 | * To encode a string, rather than binary data java.net.URLEncoder may be better. See 42 | * printable characters in the Java glossary for a discussion of the differences. 43 | * 44 | * version 1.4 2002 February 15 -- correct bugs with uneven line lengths, 45 | * allow you to configure line separator. 46 | * now need Base64 object and instance methods. 47 | * new mailing address. 48 | * version 1.3 2000 September 12 -- fix problems with estimating output length in encode 49 | * version 1.2 2000 September 09 -- now handles decode as well. 50 | * version 1.1 1999 December 04 -- more symmetrical encoding algorithm. 51 | * more accurate StringBuffer allocation size. 52 | * version 1.0 1999 December 03 -- posted in comp.lang.java.programmer. 53 | * Futures Streams or files. 54 | */ 55 | 56 | public class Base64 57 | { 58 | 59 | /** 60 | * how we separate lines, e.g. \n, \r\n, \r etc. 61 | */ 62 | private String lineSeparator = System.getProperty( "line.separator" ); 63 | 64 | /** 65 | * max chars per line, excluding lineSeparator. A multiple of 4. 66 | */ 67 | private int lineLength = 72; 68 | 69 | private char[] valueToChar = new char[64]; 70 | 71 | /** 72 | * binary value encoded by a given letter of the alphabet 0..63 73 | */ 74 | private int[] charToValue = new int[256]; 75 | 76 | private int[] charToPad = new int[4]; 77 | 78 | /* constructor */ 79 | public Base64() 80 | { 81 | this.init('+', '/', '='); 82 | } 83 | 84 | /* constructor */ 85 | public Base64(char chPlus, char chSplash, char chPad, int lineLength) 86 | { 87 | this.init(chPlus, chSplash, chPad); 88 | this.lineLength = lineLength; 89 | } 90 | 91 | public Base64(int lineLength) 92 | { 93 | this.lineLength = lineLength; 94 | } 95 | 96 | /* initialise defaultValueToChar and defaultCharToValue tables */ 97 | private void init(char chPlus, char chSplash, char chPad) 98 | { 99 | int index = 0; 100 | // build translate this.valueToChar table only once. 101 | // 0..25 -> 'A'..'Z' 102 | for ( int i='A'; i<='Z'; i++) { 103 | this.valueToChar[index++] = (char)i; 104 | } 105 | 106 | // 26..51 -> 'a'..'z' 107 | for ( int i='a'; i<='z'; i++ ) { 108 | this.valueToChar[index++] = (char)i; 109 | } 110 | 111 | // 52..61 -> '0'..'9' 112 | for ( int i='0'; i<='9'; i++) { 113 | this.valueToChar[index++] = (char)i; 114 | } 115 | 116 | this.valueToChar[index++] = chPlus; 117 | this.valueToChar[index++] = chSplash; 118 | 119 | // build translate defaultCharToValue table only once. 120 | for ( int i=0; i<256; i++ ) 121 | { 122 | this.charToValue[i] = IGNORE; // default is to ignore 123 | } 124 | 125 | for ( int i=0; i<64; i++ ) 126 | { 127 | this.charToValue[this.valueToChar[i]] = i; 128 | } 129 | 130 | this.charToValue[chPad] = PAD; 131 | java.util.Arrays.fill(this.charToPad, chPad); 132 | } 133 | 134 | /** 135 | * Encode an arbitrary array of bytes as Base64 printable ASCII. 136 | * It will be broken into lines of 72 chars each. The last line is not 137 | * terminated with a line separator. 138 | * The output will always have an even multiple of data characters, 139 | * exclusive of \n. It is padded out with =. 140 | */ 141 | public String encode(byte[] b) throws IOException 142 | { 143 | // Each group or partial group of 3 bytes becomes four chars 144 | // covered quotient 145 | int outputLength = ((b.length + 2) / 3) * 4; 146 | 147 | // account for trailing newlines, on all but the very last line 148 | if ( lineLength != 0 ) 149 | { 150 | int lines = ( outputLength + lineLength -1 ) / lineLength - 1; 151 | if ( lines > 0 ) 152 | { 153 | outputLength += lines * lineSeparator.length(); 154 | } 155 | } 156 | 157 | // must be local for recursion to work. 158 | StringBuffer sb = new StringBuffer( outputLength ); 159 | 160 | // must be local for recursion to work. 161 | int linePos = 0; 162 | 163 | // first deal with even multiples of 3 bytes. 164 | int len = (b.length / 3) * 3; 165 | int leftover = b.length - len; 166 | for ( int i=0; i lineLength ) 173 | { 174 | if ( lineLength != 0 ) 175 | { 176 | sb.append(lineSeparator); 177 | } 178 | linePos = 4; 179 | } 180 | 181 | // get next three bytes in unsigned form lined up, 182 | // in big-endian order 183 | int combined = b[i+0] & 0xff; 184 | combined <<= 8; 185 | combined |= b[i+1] & 0xff; 186 | combined <<= 8; 187 | combined |= b[i+2] & 0xff; 188 | 189 | // break those 24 bits into a 4 groups of 6 bits, 190 | // working LSB to MSB. 191 | int c3 = combined & 0x3f; 192 | combined >>>= 6; 193 | int c2 = combined & 0x3f; 194 | combined >>>= 6; 195 | int c1 = combined & 0x3f; 196 | combined >>>= 6; 197 | int c0 = combined & 0x3f; 198 | 199 | // Translate into the equivalent alpha character 200 | // emitting them in big-endian order. 201 | sb.append( valueToChar[c0]); 202 | sb.append( valueToChar[c1]); 203 | sb.append( valueToChar[c2]); 204 | sb.append( valueToChar[c3]); 205 | } 206 | 207 | // deal with leftover bytes 208 | switch ( leftover ) 209 | { 210 | case 0: 211 | default: 212 | // nothing to do 213 | break; 214 | 215 | case 1: 216 | // One leftover byte generates xx== 217 | // Start a new line if next 4 chars won't fit on the current line 218 | linePos += 4; 219 | if ( linePos > lineLength ) 220 | { 221 | 222 | if ( lineLength != 0 ) 223 | { 224 | sb.append(lineSeparator); 225 | } 226 | linePos = 4; 227 | } 228 | 229 | // Handle this recursively with a faked complete triple. 230 | // Throw away last two chars and replace with == 231 | sb.append(encode(new byte[] {b[len], 0, 0} 232 | ).substring(0,2)); 233 | sb.append("=="); 234 | break; 235 | 236 | case 2: 237 | // Two leftover bytes generates xxx= 238 | // Start a new line if next 4 chars won't fit on the current line 239 | linePos += 4; 240 | if ( linePos > lineLength ) 241 | { 242 | if ( lineLength != 0 ) 243 | { 244 | sb.append(lineSeparator); 245 | } 246 | linePos = 4; 247 | } 248 | // Handle this recursively with a faked complete triple. 249 | // Throw away last char and replace with = 250 | sb.append(encode(new byte[] {b[len], b[len+1], 0} 251 | ).substring(0,3)); 252 | sb.append("="); 253 | break; 254 | 255 | } // end switch; 256 | 257 | if ( outputLength != sb.length() ) 258 | { 259 | System.out.println("oops: minor program flaw: output length mis-estimated"); 260 | System.out.println("estimate:" + outputLength); 261 | System.out.println("actual:" + sb.length()); 262 | } 263 | return sb.toString(); 264 | }// end encode 265 | 266 | /** 267 | * decode a well-formed complete Base64 string back into an array of bytes. 268 | * It must have an even multiple of 4 data characters (not counting \n), 269 | * padded out with = as needed. 270 | */ 271 | public byte[] decodeAuto( String s) { 272 | int nRemain = s.length() % 4; 273 | if (nRemain == 0) { 274 | return this.decode(s); 275 | } else { 276 | return this.decode(s + new String(this.charToPad, 0, 4 - nRemain)); 277 | } 278 | } 279 | 280 | /** 281 | * decode a well-formed complete Base64 string back into an array of bytes. 282 | * It must have an even multiple of 4 data characters (not counting \n), 283 | * padded out with = as needed. 284 | */ 285 | public byte[] decode( String s) 286 | { 287 | 288 | // estimate worst case size of output array, no embedded newlines. 289 | byte[] b = new byte[(s.length() / 4) * 3]; 290 | 291 | // tracks where we are in a cycle of 4 input chars. 292 | int cycle = 0; 293 | 294 | // where we combine 4 groups of 6 bits and take apart as 3 groups of 8. 295 | int combined = 0; 296 | 297 | // how many bytes we have prepared. 298 | int j = 0; 299 | // will be an even multiple of 4 chars, plus some embedded \n 300 | int len = s.length(); 301 | int dummies = 0; 302 | for ( int i=0; i>>= 8; 349 | b[j+1] = (byte)combined; 350 | combined >>>= 8; 351 | b[j] = (byte)combined; 352 | j += 3; 353 | cycle = 0; 354 | break; 355 | } 356 | break; 357 | } 358 | } // end for 359 | if ( cycle != 0 ) 360 | { 361 | throw new ArrayIndexOutOfBoundsException ("Input to decode not an even multiple of 4 characters; pad with =."); 362 | } 363 | j -= dummies; 364 | if ( b.length != j ) 365 | { 366 | byte[] b2 = new byte[j]; 367 | System.arraycopy(b, 0, b2, 0, j); 368 | b = b2; 369 | } 370 | return b; 371 | 372 | }// end decode 373 | 374 | /** 375 | * determines how long the lines are that are generated by encode. 376 | * Ignored by decode. 377 | * @param length 0 means no newlines inserted. Must be a multiple of 4. 378 | */ 379 | public void setLineLength(int length) 380 | { 381 | this.lineLength = (length/4) * 4; 382 | } 383 | 384 | /** 385 | * How lines are separated. 386 | * Ignored by decode. 387 | * @param lineSeparator may be "" but not null. 388 | * Usually contains only a combination of chars \n and \r. 389 | * Could be any chars not in set A-Z a-z 0-9 + /. 390 | */ 391 | public void setLineSeparator(String lineSeparator) 392 | { 393 | this.lineSeparator = lineSeparator; 394 | } 395 | 396 | /** 397 | * Marker value for chars we just ignore, e.g. \n \r high ascii 398 | */ 399 | static final int IGNORE = -1; 400 | 401 | /** 402 | * Marker for = trailing pad 403 | */ 404 | static final int PAD = -2; 405 | 406 | /** 407 | * used to disable test driver 408 | */ 409 | private static final boolean debug = true; 410 | 411 | /** 412 | * debug display array 413 | */ 414 | public static void show (byte[] b) 415 | { 416 | int count = 0; 417 | int rows = 0; 418 | 419 | 420 | for ( int i=0; i> it = props.entrySet().iterator(); 152 | while (it.hasNext()) { 153 | Map.Entry entry = it.next(); 154 | name= entry.getKey().toString(); 155 | value = entry.getValue().toString(); 156 | obj = this.paramTable.get(name); 157 | if (obj == null) 158 | { 159 | this.paramTable.put(name, value); 160 | } 161 | else if (obj instanceof String) 162 | { 163 | valueList = new ArrayList(); 164 | valueList.add(obj); 165 | valueList.add(value); 166 | this.paramTable.put(name, valueList); 167 | } 168 | else 169 | { 170 | valueList = (ArrayList)obj; 171 | valueList.add(value); 172 | } 173 | } 174 | } 175 | finally 176 | { 177 | if (is != null) { 178 | is.close(); 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/common/MyException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | */ 8 | 9 | package fileserver.dfsserver.org.csource.common; 10 | 11 | /** 12 | * My Exception 13 | * @author Happy Fish / YuQing 14 | * @version Version 1.0 15 | */ 16 | public class MyException extends Exception 17 | { 18 | public MyException() 19 | { 20 | } 21 | 22 | public MyException(String message) 23 | { 24 | super(message); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/common/NameValuePair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | */ 8 | 9 | package fileserver.dfsserver.org.csource.common; 10 | 11 | /** 12 | * name(key) and value pair model 13 | * @author Happy Fish / YuQing 14 | * @version Version 1.0 15 | */ 16 | public class NameValuePair 17 | { 18 | protected String name; 19 | protected String value; 20 | 21 | public NameValuePair() 22 | { 23 | } 24 | 25 | public NameValuePair(String name) 26 | { 27 | this.name = name; 28 | } 29 | 30 | public NameValuePair(String name, String value) 31 | { 32 | this.name = name; 33 | this.value = value; 34 | } 35 | 36 | public String getName() 37 | { 38 | return this.name; 39 | } 40 | 41 | public String getValue() 42 | { 43 | return this.value; 44 | } 45 | 46 | public void setName(String name) 47 | { 48 | this.name = name; 49 | } 50 | 51 | public void setValue(String value) 52 | { 53 | this.value = value; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/ClientGlobal.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs; 10 | 11 | import java.net.*; 12 | import java.io.*; 13 | import java.net.*; 14 | import fileserver.dfsserver.org.csource.common.*; 15 | 16 | /** 17 | * Global variables 18 | * @author Happy Fish / YuQing 19 | * @version Version 1.11 20 | */ 21 | public class ClientGlobal 22 | { 23 | public static int g_connect_timeout; //millisecond 24 | public static int g_network_timeout; //millisecond 25 | public static String g_charset; 26 | public static int g_tracker_http_port; 27 | public static boolean g_anti_steal_token; //if anti-steal token 28 | public static String g_secret_key; //generage token secret key 29 | public static TrackerGroup g_tracker_group; 30 | 31 | public static final int DEFAULT_CONNECT_TIMEOUT = 5; //second 32 | public static final int DEFAULT_NETWORK_TIMEOUT = 30; //second 33 | 34 | private ClientGlobal() 35 | { 36 | } 37 | 38 | /** 39 | * load global variables 40 | * @param conf_filename config filename 41 | */ 42 | public static void init(String conf_filename) throws FileNotFoundException, IOException, MyException 43 | { 44 | IniFileReader iniReader; 45 | String[] szTrackerServers; 46 | String[] parts; 47 | 48 | iniReader = new IniFileReader(conf_filename); 49 | 50 | g_connect_timeout = iniReader.getIntValue("connect_timeout", DEFAULT_CONNECT_TIMEOUT); 51 | if (g_connect_timeout < 0) 52 | { 53 | g_connect_timeout = DEFAULT_CONNECT_TIMEOUT; 54 | } 55 | g_connect_timeout *= 1000; //millisecond 56 | 57 | g_network_timeout = iniReader.getIntValue("network_timeout", DEFAULT_NETWORK_TIMEOUT); 58 | if (g_network_timeout < 0) 59 | { 60 | g_network_timeout = DEFAULT_NETWORK_TIMEOUT; 61 | } 62 | g_network_timeout *= 1000; //millisecond 63 | 64 | g_charset = iniReader.getStrValue("charset"); 65 | if (g_charset == null || g_charset.length() == 0) 66 | { 67 | g_charset = "ISO8859-1"; 68 | } 69 | 70 | szTrackerServers = iniReader.getValues("tracker_server"); 71 | if (szTrackerServers == null) 72 | { 73 | throw new MyException("item \"tracker_server\" in " + conf_filename + " not found"); 74 | } 75 | 76 | InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length]; 77 | for (int i=0; i= this.tracker_servers.length) 63 | { 64 | this.tracker_server_index = 0; 65 | } 66 | 67 | current_index = this.tracker_server_index; 68 | } 69 | 70 | try 71 | { 72 | return this.getConnection(current_index); 73 | } 74 | catch(IOException ex) 75 | { 76 | System.err.println("connect to server " + this.tracker_servers[current_index].getAddress().getHostAddress() + ":" + this.tracker_servers[current_index].getPort() + " fail"); 77 | ex.printStackTrace(System.err); 78 | } 79 | 80 | for (int i=0; i 0) 41 | { 42 | try 43 | { 44 | if ((bytes=inputStream.read(buff, 0, remainBytes > buff.length ? buff.length : (int)remainBytes)) < 0) 45 | { 46 | return -1; 47 | } 48 | } 49 | catch(IOException ex) 50 | { 51 | ex.printStackTrace(); 52 | return -1; 53 | } 54 | 55 | out.write(buff, 0, bytes); 56 | remainBytes -= bytes; 57 | } 58 | 59 | return 0; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/DownloadFileWriter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | */ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.util.*; 13 | import java.net.*; 14 | import fileserver.dfsserver.org.csource.fastdfs.*; 15 | 16 | /** 17 | * DowloadCallback test 18 | * @author Happy Fish / YuQing 19 | * @version Version 1.3 20 | */ 21 | public class DownloadFileWriter implements DownloadCallback 22 | { 23 | private String filename; 24 | private FileOutputStream out = null; 25 | private long current_bytes = 0; 26 | 27 | public DownloadFileWriter(String filename) 28 | { 29 | this.filename = filename; 30 | } 31 | 32 | public int recv(long file_size, byte[] data, int bytes) 33 | { 34 | try 35 | { 36 | if (this.out == null) 37 | { 38 | this.out = new FileOutputStream(this.filename); 39 | } 40 | 41 | this.out.write(data, 0, bytes); 42 | this.current_bytes += bytes; 43 | 44 | if (this.current_bytes == file_size) 45 | { 46 | this.out.close(); 47 | this.out = null; 48 | this.current_bytes = 0; 49 | } 50 | } 51 | catch(IOException ex) 52 | { 53 | ex.printStackTrace(); 54 | return -1; 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | protected void finalize() throws Throwable 61 | { 62 | if (this.out != null) 63 | { 64 | this.out.close(); 65 | this.out = null; 66 | } 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/Monitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.text.SimpleDateFormat; 12 | import fileserver.dfsserver.org.csource.common.*; 13 | import fileserver.dfsserver.org.csource.fastdfs.*; 14 | 15 | /** 16 | * load test class 17 | * @author Happy Fish / YuQing 18 | * @version Version 1.20 19 | */ 20 | public class Monitor 21 | { 22 | private Monitor() 23 | { 24 | } 25 | 26 | /** 27 | * entry point 28 | * @param args comand arguments 29 | *
  • args[0]: config filename
30 | */ 31 | public static void main(String args[]) 32 | { 33 | if (args.length < 1) 34 | { 35 | System.out.println("Error: Must have 1 parameter: config filename"); 36 | return; 37 | } 38 | 39 | System.out.println("java.version=" + System.getProperty("java.version")); 40 | 41 | try 42 | { 43 | ClientGlobal.init(args[0]); 44 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 45 | System.out.println("charset=" + ClientGlobal.g_charset); 46 | 47 | TrackerClient tracker = new TrackerClient(); 48 | 49 | /* 50 | System.out.println("delete storage return: " + tracker.deleteStorage("group1", "192.168.0.192")); 51 | System.out.println("delete storage errno: " + tracker.getErrorCode()); 52 | */ 53 | 54 | TrackerServer trackerServer = tracker.getConnection(); 55 | if (trackerServer == null) 56 | { 57 | return; 58 | } 59 | 60 | int count; 61 | StructGroupStat[] groupStats = tracker.listGroups(trackerServer); 62 | if (groupStats == null) 63 | { 64 | System.out.println(""); 65 | System.out.println("ERROR! list groups error, error no: " + tracker.getErrorCode()); 66 | System.out.println(""); 67 | return; 68 | } 69 | 70 | System.out.println("group count: " + groupStats.length); 71 | 72 | count = 0; 73 | for (StructGroupStat groupStat : groupStats) 74 | { 75 | count++; 76 | System.out.println("Group " + count + ":"); 77 | System.out.println("group name = " + groupStat.getGroupName()); 78 | System.out.println("disk total space = " + groupStat.getTotalMB() + "MB"); 79 | System.out.println("disk free space = " + groupStat.getFreeMB() + " MB"); 80 | System.out.println("trunk free space = " + groupStat.getTrunkFreeMB() + " MB"); 81 | System.out.println("storage server count = " + groupStat.getStorageCount()); 82 | System.out.println("active server count = " + groupStat.getActiveCount()); 83 | System.out.println("storage server port = " + groupStat.getStoragePort()); 84 | System.out.println("storage HTTP port = " + groupStat.getStorageHttpPort()); 85 | System.out.println("store path count = " + groupStat.getStorePathCount()); 86 | System.out.println("subdir count per path = " + groupStat.getSubdirCountPerPath()); 87 | System.out.println("current write server index = " + groupStat.getCurrentWriteServer()); 88 | System.out.println("current trunk file id = " + groupStat.getCurrentTrunkFileId()); 89 | 90 | StructStorageStat[] storageStats = tracker.listStorages(trackerServer, groupStat.getGroupName()); 91 | if (storageStats == null) 92 | { 93 | System.out.println(""); 94 | System.out.println("ERROR! list storage error, error no: " + tracker.getErrorCode()); 95 | System.out.println(""); 96 | break; 97 | } 98 | 99 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 100 | int stroageCount = 0; 101 | for (StructStorageStat storageStat : storageStats) 102 | { 103 | stroageCount++; 104 | System.out.println("\tStorage " + stroageCount + ":"); 105 | System.out.println("\t\tstorage id = " + storageStat.getId()); 106 | System.out.println("\t\tip_addr = " + storageStat.getIpAddr() + " " + ProtoCommon.getStorageStatusCaption(storageStat.getStatus())); 107 | System.out.println("\t\thttp domain = " + storageStat.getDomainName()); 108 | System.out.println("\t\tversion = " + storageStat.getVersion()); 109 | System.out.println("\t\tjoin time = " + df.format(storageStat.getJoinTime())); 110 | System.out.println("\t\tup time = " + (storageStat.getUpTime().getTime() == 0 ? "" : df.format(storageStat.getUpTime()))); 111 | System.out.println("\t\ttotal storage = " + storageStat.getTotalMB() + "MB"); 112 | System.out.println("\t\tfree storage = " + storageStat.getFreeMB() + "MB"); 113 | System.out.println("\t\tupload priority = " + storageStat.getUploadPriority()); 114 | System.out.println("\t\tstore_path_count = " + storageStat.getStorePathCount()); 115 | System.out.println("\t\tsubdir_count_per_path = " + storageStat.getSubdirCountPerPath()); 116 | System.out.println("\t\tstorage_port = " + storageStat.getStoragePort()); 117 | System.out.println("\t\tstorage_http_port = " + storageStat.getStorageHttpPort()); 118 | System.out.println("\t\tcurrent_write_path = " + storageStat.getCurrentWritePath()); 119 | System.out.println("\t\tsource ip_addr = " + storageStat.getSrcIpAddr()); 120 | System.out.println("\t\tif_trunk_server = " + storageStat.isTrunkServer()); 121 | System.out.println("\t\tconntion.alloc_count = " + storageStat.getConnectionAllocCount()); 122 | System.out.println("\t\tconntion.current_count = " + storageStat.getConnectionCurrentCount()); 123 | System.out.println("\t\tconntion.max_count = " + storageStat.getConnectionMaxCount()); 124 | System.out.println("\t\ttotal_upload_count = " + storageStat.getTotalUploadCount()); 125 | System.out.println("\t\tsuccess_upload_count = " + storageStat.getSuccessUploadCount()); 126 | System.out.println("\t\ttotal_append_count = " + storageStat.getTotalAppendCount()); 127 | System.out.println("\t\tsuccess_append_count = " + storageStat.getSuccessAppendCount()); 128 | System.out.println("\t\ttotal_modify_count = " + storageStat.getTotalModifyCount()); 129 | System.out.println("\t\tsuccess_modify_count = " + storageStat.getSuccessModifyCount()); 130 | System.out.println("\t\ttotal_truncate_count = " + storageStat.getTotalTruncateCount()); 131 | System.out.println("\t\tsuccess_truncate_count = " + storageStat.getSuccessTruncateCount()); 132 | System.out.println("\t\ttotal_set_meta_count = " + storageStat.getTotalSetMetaCount()); 133 | System.out.println("\t\tsuccess_set_meta_count = " + storageStat.getSuccessSetMetaCount()); 134 | System.out.println("\t\ttotal_delete_count = " + storageStat.getTotalDeleteCount()); 135 | System.out.println("\t\tsuccess_delete_count = " + storageStat.getSuccessDeleteCount()); 136 | System.out.println("\t\ttotal_download_count = " + storageStat.getTotalDownloadCount()); 137 | System.out.println("\t\tsuccess_download_count = " + storageStat.getSuccessDownloadCount()); 138 | System.out.println("\t\ttotal_get_meta_count = " + storageStat.getTotalGetMetaCount()); 139 | System.out.println("\t\tsuccess_get_meta_count = " + storageStat.getSuccessGetMetaCount()); 140 | System.out.println("\t\ttotal_create_link_count = " + storageStat.getTotalCreateLinkCount()); 141 | System.out.println("\t\tsuccess_create_link_count = " + storageStat.getSuccessCreateLinkCount()); 142 | System.out.println("\t\ttotal_delete_link_count = " + storageStat.getTotalDeleteLinkCount()); 143 | System.out.println("\t\tsuccess_delete_link_count = " + storageStat.getSuccessDeleteLinkCount()); 144 | System.out.println("\t\ttotal_upload_bytes = " + storageStat.getTotalUploadBytes()); 145 | System.out.println("\t\tsuccess_upload_bytes = " + storageStat.getSuccessUploadBytes()); 146 | System.out.println("\t\ttotal_append_bytes = " + storageStat.getTotalAppendBytes()); 147 | System.out.println("\t\tsuccess_append_bytes = " + storageStat.getSuccessAppendBytes()); 148 | System.out.println("\t\ttotal_modify_bytes = " + storageStat.getTotalModifyBytes()); 149 | System.out.println("\t\tsuccess_modify_bytes = " + storageStat.getSuccessModifyBytes()); 150 | System.out.println("\t\ttotal_download_bytes = " + storageStat.getTotalDownloadloadBytes()); 151 | System.out.println("\t\tsuccess_download_bytes = " + storageStat.getSuccessDownloadloadBytes()); 152 | System.out.println("\t\ttotal_sync_in_bytes = " + storageStat.getTotalSyncInBytes()); 153 | System.out.println("\t\tsuccess_sync_in_bytes = " + storageStat.getSuccessSyncInBytes()); 154 | System.out.println("\t\ttotal_sync_out_bytes = " + storageStat.getTotalSyncOutBytes()); 155 | System.out.println("\t\tsuccess_sync_out_bytes = " + storageStat.getSuccessSyncOutBytes()); 156 | System.out.println("\t\ttotal_file_open_count = " + storageStat.getTotalFileOpenCount()); 157 | System.out.println("\t\tsuccess_file_open_count = " + storageStat.getSuccessFileOpenCount()); 158 | System.out.println("\t\ttotal_file_read_count = " + storageStat.getTotalFileReadCount()); 159 | System.out.println("\t\tsuccess_file_read_count = " + storageStat.getSuccessFileReadCount()); 160 | System.out.println("\t\ttotal_file_write_count = " + storageStat.getTotalFileWriteCount()); 161 | System.out.println("\t\tsuccess_file_write_count = " + storageStat.getSuccessFileWriteCount()); 162 | System.out.println("\t\tlast_heart_beat_time = " + df.format(storageStat.getLastHeartBeatTime())); 163 | System.out.println("\t\tlast_source_update = " + df.format(storageStat.getLastSourceUpdate())); 164 | System.out.println("\t\tlast_sync_update = " + df.format(storageStat.getLastSyncUpdate())); 165 | System.out.println("\t\tlast_synced_timestamp = " + df.format(storageStat.getLastSyncedTimestamp()) + getSyncedDelayString(storageStats, storageStat)); 166 | } 167 | } 168 | 169 | trackerServer.close(); 170 | } 171 | catch(Exception ex) 172 | { 173 | ex.printStackTrace(); 174 | } 175 | } 176 | 177 | protected static String getSyncedDelayString(StructStorageStat[] storageStats, StructStorageStat currentStorageStat) 178 | { 179 | long maxLastSourceUpdate = 0; 180 | for (StructStorageStat storageStat : storageStats) 181 | { 182 | if (storageStat != currentStorageStat && storageStat.getLastSourceUpdate().getTime() > maxLastSourceUpdate) 183 | { 184 | maxLastSourceUpdate = storageStat.getLastSourceUpdate().getTime(); 185 | } 186 | } 187 | 188 | if (maxLastSourceUpdate == 0) 189 | { 190 | return ""; 191 | } 192 | 193 | if (currentStorageStat.getLastSyncedTimestamp().getTime() == 0) 194 | { 195 | return " (never synced)"; 196 | } 197 | 198 | int delaySeconds = (int)((maxLastSourceUpdate - currentStorageStat.getLastSyncedTimestamp().getTime()) / 1000); 199 | int day = delaySeconds / (24 * 3600); 200 | int remainSeconds = delaySeconds % (24 * 3600); 201 | int hour = remainSeconds / 3600; 202 | remainSeconds %= 3600; 203 | int minute = remainSeconds / 60; 204 | int second = remainSeconds % 60; 205 | String delayTimeStr; 206 | if (day != 0) 207 | { 208 | delayTimeStr = String.format("%1$d days %2$02dh:%3$02dm:%4$02ds", day, hour, minute, second); 209 | } 210 | else if (hour != 0) 211 | { 212 | delayTimeStr = String.format("%1$02dh:%2$02dm:%3$02ds", hour, minute, second); 213 | } 214 | else if (minute != 0) 215 | { 216 | delayTimeStr = String.format("%1$02dm:%2$02ds", minute, second); 217 | } 218 | else 219 | { 220 | delayTimeStr = String.format("%1$ds", second); 221 | } 222 | 223 | return " (" + delayTimeStr + " delay)"; 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/Test.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.net.*; 13 | import java.util.*; 14 | import fileserver.dfsserver.org.csource.common.*; 15 | import fileserver.dfsserver.org.csource.fastdfs.*; 16 | 17 | /** 18 | * client test 19 | * @author Happy Fish / YuQing 20 | * @version Version 1.18 21 | */ 22 | public class Test 23 | { 24 | private Test() 25 | { 26 | } 27 | 28 | /** 29 | * entry point 30 | * @param args comand arguments 31 | *
  • args[0]: config filename
32 | *
  • args[1]: local filename to upload
33 | */ 34 | public static void main(String args[]) 35 | { 36 | if (args.length < 2) 37 | { 38 | System.out.println("Error: Must have 2 parameters, one is config filename, " 39 | + "the other is the local filename to upload"); 40 | return; 41 | } 42 | 43 | System.out.println("java.version=" + System.getProperty("java.version")); 44 | 45 | String conf_filename = args[0]; 46 | String local_filename = args[1]; 47 | 48 | try 49 | { 50 | ClientGlobal.init(conf_filename); 51 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 52 | System.out.println("charset=" + ClientGlobal.g_charset); 53 | 54 | TrackerClient tracker = new TrackerClient(); 55 | TrackerServer trackerServer = tracker.getConnection(); 56 | StorageServer storageServer = null; 57 | StorageClient1 client = new StorageClient1(trackerServer, storageServer); 58 | 59 | NameValuePair[] metaList = new NameValuePair[1]; 60 | metaList[0] = new NameValuePair("fileName", local_filename); 61 | String fileId = client.upload_file1(local_filename, null, metaList); 62 | System.out.println("upload success. file id is: " + fileId); 63 | 64 | int i = 0; 65 | while (i++ < 10) { 66 | byte[] result = client.download_file1(fileId); 67 | System.out.println(i + ", download result is: " + result.length); 68 | } 69 | 70 | trackerServer.close(); 71 | } 72 | catch(Exception ex) 73 | { 74 | ex.printStackTrace(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/Test1.java: -------------------------------------------------------------------------------- 1 | 2 | package fileserver.dfsserver.org.csource.fastdfs.test; 3 | 4 | import java.io.*; 5 | import java.net.*; 6 | import java.util.*; 7 | import fileserver.dfsserver.org.csource.common.*; 8 | import fileserver.dfsserver.org.csource.fastdfs.*; 9 | 10 | public class Test1 11 | { 12 | public static void main(String args[]) 13 | { 14 | try 15 | { 16 | ClientGlobal.init("fdfs_client.conf"); 17 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 18 | System.out.println("charset=" + ClientGlobal.g_charset); 19 | 20 | TrackerGroup tg = new TrackerGroup(new InetSocketAddress[]{new InetSocketAddress("10.0.11.243", 22122)}); 21 | TrackerClient tc = new TrackerClient(tg); 22 | 23 | TrackerServer ts = tc.getConnection(); 24 | if (ts == null) 25 | { 26 | System.out.println("getConnection return null"); 27 | return; 28 | } 29 | 30 | StorageServer ss = tc.getStoreStorage(ts); 31 | if (ss == null) 32 | { 33 | System.out.println("getStoreStorage return null"); 34 | } 35 | 36 | StorageClient1 sc1 = new StorageClient1(ts, ss); 37 | 38 | NameValuePair[] meta_list = null; //new NameValuePair[0]; 39 | String item; 40 | String fileid; 41 | if (System.getProperty("os.name").equalsIgnoreCase("windows")) 42 | { 43 | item = "c:/windows/system32/notepad.exe"; 44 | fileid = sc1.upload_file1(item, "exe", meta_list); 45 | } 46 | else 47 | { 48 | item = "/etc/hosts"; 49 | fileid = sc1.upload_file1(item, "", meta_list); 50 | } 51 | 52 | System.out.println("Upload local file "+item+" ok, fileid="+fileid); 53 | } 54 | catch(Exception ex) 55 | { 56 | ex.printStackTrace(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/TestAppender.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.net.*; 13 | import java.util.*; 14 | import fileserver.dfsserver.org.csource.common.*; 15 | import fileserver.dfsserver.org.csource.fastdfs.*; 16 | 17 | /** 18 | * client test 19 | * @author Happy Fish / YuQing 20 | * @version Version 1.20 21 | */ 22 | public class TestAppender 23 | { 24 | private TestAppender() 25 | { 26 | } 27 | 28 | /** 29 | * entry point 30 | * @param args comand arguments 31 | *
  • args[0]: config filename
32 | *
  • args[1]: local filename to upload
33 | */ 34 | public static void main(String args[]) 35 | { 36 | if (args.length < 2) 37 | { 38 | System.out.println("Error: Must have 2 parameters, one is config filename, " 39 | + "the other is the local filename to upload"); 40 | return; 41 | } 42 | 43 | System.out.println("java.version=" + System.getProperty("java.version")); 44 | 45 | String conf_filename = args[0]; 46 | String local_filename = args[1]; 47 | 48 | try 49 | { 50 | ClientGlobal.init(conf_filename); 51 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 52 | System.out.println("charset=" + ClientGlobal.g_charset); 53 | 54 | long startTime; 55 | String group_name; 56 | String remote_filename; 57 | ServerInfo[] servers; 58 | TrackerClient tracker = new TrackerClient(); 59 | TrackerServer trackerServer = tracker.getConnection(); 60 | 61 | StorageServer storageServer = null; 62 | 63 | /* 64 | storageServer = tracker.getStoreStorage(trackerServer); 65 | if (storageServer == null) 66 | { 67 | System.out.println("getStoreStorage fail, error code: " + tracker.getErrorCode()); 68 | return; 69 | } 70 | */ 71 | 72 | StorageClient client = new StorageClient(trackerServer, storageServer); 73 | byte[] file_buff; 74 | NameValuePair[] meta_list; 75 | String[] results; 76 | String appender_filename; 77 | String file_ext_name; 78 | int errno; 79 | 80 | meta_list = new NameValuePair[4]; 81 | meta_list[0] = new NameValuePair("width", "800"); 82 | meta_list[1] = new NameValuePair("heigth", "600"); 83 | meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); 84 | meta_list[3] = new NameValuePair("author", "Mike"); 85 | 86 | file_buff = "this is a test".getBytes(ClientGlobal.g_charset); 87 | System.out.println("file length: " + file_buff.length); 88 | 89 | group_name = null; 90 | StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); 91 | if (storageServers == null) 92 | { 93 | System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); 94 | } 95 | else 96 | { 97 | System.err.println("store storage servers count: " + storageServers.length); 98 | for (int k=0; k 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) 277 | { 278 | file_ext_name = local_filename.substring(nPos+1); 279 | } 280 | else 281 | { 282 | file_ext_name = null; 283 | } 284 | 285 | results = client.upload_appender_file(null, f.length(), 286 | new UploadLocalFileSender(local_filename), file_ext_name, meta_list); 287 | if (results != null) 288 | { 289 | group_name = results[0]; 290 | remote_filename = results[1]; 291 | 292 | System.out.println("group name: " + group_name + ", remote filename: " + remote_filename); 293 | System.out.println(client.get_file_info(group_name, remote_filename)); 294 | 295 | appender_filename = remote_filename; 296 | startTime = System.currentTimeMillis(); 297 | errno = client.append_file(group_name, appender_filename, f.length(), new UploadLocalFileSender(local_filename)); 298 | System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); 299 | if (errno == 0) 300 | { 301 | System.err.println(client.get_file_info(group_name, appender_filename)); 302 | } 303 | else 304 | { 305 | System.err.println("append file fail, error no: " + errno); 306 | } 307 | 308 | startTime = System.currentTimeMillis(); 309 | errno = client.modify_file(group_name, appender_filename, 0, f.length(), new UploadLocalFileSender(local_filename)); 310 | System.out.println("modify_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); 311 | if (errno == 0) 312 | { 313 | System.err.println(client.get_file_info(group_name, appender_filename)); 314 | } 315 | else 316 | { 317 | System.err.println("modify file fail, error no: " + errno); 318 | } 319 | 320 | startTime = System.currentTimeMillis(); 321 | errno = client.truncate_file(group_name, appender_filename); 322 | System.out.println("truncate_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); 323 | if (errno == 0) 324 | { 325 | System.err.println(client.get_file_info(group_name, appender_filename)); 326 | } 327 | else 328 | { 329 | System.err.println("truncate file fail, error no: " + errno); 330 | } 331 | } 332 | else 333 | { 334 | System.err.println("Upload file fail, error no: " + errno); 335 | } 336 | 337 | storageServer = tracker.getFetchStorage(trackerServer, group_name, remote_filename); 338 | if (storageServer == null) 339 | { 340 | System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); 341 | return; 342 | } 343 | /* for test only */ 344 | System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); 345 | 346 | storageServer.close(); 347 | 348 | /* for test only */ 349 | System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); 350 | 351 | trackerServer.close(); 352 | } 353 | catch(Exception ex) 354 | { 355 | ex.printStackTrace(); 356 | } 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/TestAppender1.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.net.*; 13 | import java.util.*; 14 | import fileserver.dfsserver.org.csource.common.*; 15 | import fileserver.dfsserver.org.csource.fastdfs.*; 16 | 17 | /** 18 | * client test 19 | * @author Happy Fish / YuQing 20 | * @version Version 1.20 21 | */ 22 | public class TestAppender1 23 | { 24 | private TestAppender1() 25 | { 26 | } 27 | 28 | /** 29 | * entry point 30 | * @param args comand arguments 31 | *
  • args[0]: config filename
32 | *
  • args[1]: local filename to upload
33 | */ 34 | public static void main(String args[]) 35 | { 36 | if (args.length < 2) 37 | { 38 | System.out.println("Error: Must have 2 parameters, one is config filename, " 39 | + "the other is the local filename to upload"); 40 | return; 41 | } 42 | 43 | System.out.println("java.version=" + System.getProperty("java.version")); 44 | 45 | String conf_filename = args[0]; 46 | String local_filename = args[1]; 47 | 48 | try 49 | { 50 | ClientGlobal.init(conf_filename); 51 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 52 | System.out.println("charset=" + ClientGlobal.g_charset); 53 | 54 | long startTime; 55 | ServerInfo[] servers; 56 | TrackerClient tracker = new TrackerClient(); 57 | TrackerServer trackerServer = tracker.getConnection(); 58 | 59 | StorageServer storageServer = null; 60 | 61 | /* 62 | storageServer = tracker.getStoreStorage(trackerServer); 63 | if (storageServer == null) 64 | { 65 | System.out.println("getStoreStorage fail, error code: " + tracker.getErrorCode()); 66 | return; 67 | } 68 | */ 69 | 70 | StorageClient1 client = new StorageClient1(trackerServer, storageServer); 71 | byte[] file_buff; 72 | NameValuePair[] meta_list; 73 | String group_name; 74 | String appender_file_id; 75 | String file_ext_name; 76 | int errno; 77 | 78 | meta_list = new NameValuePair[4]; 79 | meta_list[0] = new NameValuePair("width", "800"); 80 | meta_list[1] = new NameValuePair("heigth", "600"); 81 | meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); 82 | meta_list[3] = new NameValuePair("author", "Mike"); 83 | 84 | file_buff = "this is a test".getBytes(ClientGlobal.g_charset); 85 | System.out.println("file length: " + file_buff.length); 86 | 87 | group_name = null; 88 | StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); 89 | if (storageServers == null) 90 | { 91 | System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); 92 | } 93 | else 94 | { 95 | System.err.println("store storage servers count: " + storageServers.length); 96 | for (int k=0; k 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) 262 | { 263 | file_ext_name = local_filename.substring(nPos+1); 264 | } 265 | else 266 | { 267 | file_ext_name = null; 268 | } 269 | 270 | appender_file_id = client.upload_appender_file1(null, f.length(), 271 | new UploadLocalFileSender(local_filename), file_ext_name, meta_list); 272 | if (appender_file_id != null) 273 | { 274 | System.out.println(client.get_file_info1(appender_file_id)); 275 | 276 | startTime = System.currentTimeMillis(); 277 | errno = client.append_file1(appender_file_id, f.length(), new UploadLocalFileSender(local_filename)); 278 | System.out.println("append_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); 279 | if (errno == 0) 280 | { 281 | System.err.println(client.get_file_info1(appender_file_id)); 282 | } 283 | else 284 | { 285 | System.err.println("append file fail, error no: " + errno); 286 | } 287 | 288 | startTime = System.currentTimeMillis(); 289 | errno = client.modify_file1(appender_file_id, 0, f.length(), new UploadLocalFileSender(local_filename)); 290 | System.out.println("modify_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); 291 | if (errno == 0) 292 | { 293 | System.err.println(client.get_file_info1(appender_file_id)); 294 | } 295 | else 296 | { 297 | System.err.println("modify file fail, error no: " + errno); 298 | } 299 | 300 | startTime = System.currentTimeMillis(); 301 | errno = client.truncate_file1(appender_file_id, 0); 302 | System.out.println("truncate_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); 303 | if (errno == 0) 304 | { 305 | System.err.println(client.get_file_info1(appender_file_id)); 306 | } 307 | else 308 | { 309 | System.err.println("truncate file fail, error no: " + errno); 310 | } 311 | } 312 | else 313 | { 314 | System.err.println("Upload file fail, error no: " + errno); 315 | } 316 | 317 | storageServer = tracker.getFetchStorage1(trackerServer, appender_file_id); 318 | if (storageServer == null) 319 | { 320 | System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); 321 | return; 322 | } 323 | /* for test only */ 324 | System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); 325 | 326 | storageServer.close(); 327 | 328 | /* for test only */ 329 | System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); 330 | 331 | trackerServer.close(); 332 | } 333 | catch(Exception ex) 334 | { 335 | ex.printStackTrace(); 336 | } 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/TestClient.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.net.*; 13 | import java.util.*; 14 | import fileserver.dfsserver.org.csource.common.*; 15 | import fileserver.dfsserver.org.csource.fastdfs.*; 16 | 17 | /** 18 | * client test 19 | * @author Happy Fish / YuQing 20 | * @version Version 1.18 21 | */ 22 | public class TestClient 23 | { 24 | private TestClient() 25 | { 26 | } 27 | 28 | /** 29 | * entry point 30 | * @param args comand arguments 31 | *
  • args[0]: config filename
32 | *
  • args[1]: local filename to upload
33 | */ 34 | public static void main(String args[]) 35 | { 36 | if (args.length < 2) 37 | { 38 | System.out.println("Error: Must have 2 parameters, one is config filename, " 39 | + "the other is the local filename to upload"); 40 | return; 41 | } 42 | 43 | System.out.println("java.version=" + System.getProperty("java.version")); 44 | 45 | String conf_filename = args[0]; 46 | String local_filename = args[1]; 47 | 48 | try 49 | { 50 | ClientGlobal.init(conf_filename); 51 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 52 | System.out.println("charset=" + ClientGlobal.g_charset); 53 | 54 | long startTime; 55 | String group_name; 56 | String remote_filename; 57 | ServerInfo[] servers; 58 | TrackerClient tracker = new TrackerClient(); 59 | TrackerServer trackerServer = tracker.getConnection(); 60 | 61 | StorageServer storageServer = null; 62 | 63 | /* 64 | storageServer = tracker.getStoreStorage(trackerServer); 65 | if (storageServer == null) 66 | { 67 | System.out.println("getStoreStorage fail, error code: " + tracker.getErrorCode()); 68 | return; 69 | } 70 | */ 71 | 72 | StorageClient client = new StorageClient(trackerServer, storageServer); 73 | byte[] file_buff; 74 | NameValuePair[] meta_list; 75 | String[] results; 76 | String master_filename; 77 | String prefix_name; 78 | String file_ext_name; 79 | String generated_slave_filename; 80 | int errno; 81 | 82 | meta_list = new NameValuePair[4]; 83 | meta_list[0] = new NameValuePair("width", "800"); 84 | meta_list[1] = new NameValuePair("heigth", "600"); 85 | meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF"); 86 | meta_list[3] = new NameValuePair("author", "Mike"); 87 | 88 | file_buff = "this is a test".getBytes(ClientGlobal.g_charset); 89 | System.out.println("file length: " + file_buff.length); 90 | 91 | group_name = null; 92 | StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); 93 | if (storageServers == null) 94 | { 95 | System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); 96 | } 97 | else 98 | { 99 | System.err.println("store storage servers count: " + storageServers.length); 100 | for (int k=0; k 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) 289 | { 290 | file_ext_name = local_filename.substring(nPos+1); 291 | } 292 | else 293 | { 294 | file_ext_name = null; 295 | } 296 | 297 | results = client.upload_file(null, f.length(), 298 | new UploadLocalFileSender(local_filename), file_ext_name, meta_list); 299 | if (results != null) 300 | { 301 | group_name = results[0]; 302 | remote_filename = results[1]; 303 | 304 | System.out.println("group name: " + group_name + ", remote filename: " + remote_filename); 305 | System.out.println(client.get_file_info(group_name, remote_filename)); 306 | 307 | master_filename = remote_filename; 308 | prefix_name = "-part3"; 309 | startTime = System.currentTimeMillis(); 310 | results = client.upload_file(group_name, master_filename, prefix_name, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); 311 | System.out.println("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms"); 312 | if (results != null) 313 | { 314 | System.err.println("slave file group_name: " + results[0] + ", remote_filename: " + results[1]); 315 | 316 | generated_slave_filename = ProtoCommon.genSlaveFilename(master_filename, prefix_name, file_ext_name); 317 | if (!generated_slave_filename.equals(results[1])) 318 | { 319 | System.err.println("generated slave file: " + generated_slave_filename + "\n != returned slave file: " + results[1]); 320 | } 321 | 322 | System.err.println(client.get_file_info(results[0], results[1])); 323 | } 324 | } 325 | else 326 | { 327 | System.err.println("Upload file fail, error no: " + errno); 328 | } 329 | 330 | storageServer = tracker.getFetchStorage(trackerServer, group_name, remote_filename); 331 | if (storageServer == null) 332 | { 333 | System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); 334 | return; 335 | } 336 | /* for test only */ 337 | System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); 338 | 339 | storageServer.close(); 340 | 341 | /* for test only */ 342 | System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); 343 | 344 | trackerServer.close(); 345 | } 346 | catch(Exception ex) 347 | { 348 | ex.printStackTrace(); 349 | } 350 | } 351 | } 352 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/TestClient1.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.net.*; 13 | import java.util.*; 14 | import fileserver.dfsserver.org.csource.common.*; 15 | import fileserver.dfsserver.org.csource.fastdfs.*; 16 | 17 | /** 18 | * client test 19 | * @author Happy Fish / YuQing 20 | * @version Version 1.16 21 | */ 22 | public class TestClient1 23 | { 24 | private TestClient1() 25 | { 26 | } 27 | 28 | /** 29 | * entry point 30 | * @param args comand arguments 31 | *
  • args[0]: config filename
32 | *
  • args[1]: local filename to upload
33 | */ 34 | public static void main(String args[]) 35 | { 36 | if (args.length < 2) 37 | { 38 | System.out.println("Error: Must have 2 parameters, one is config filename, " 39 | + "the other is the local filename to upload"); 40 | return; 41 | } 42 | 43 | System.out.println("java.version=" + System.getProperty("java.version")); 44 | 45 | String conf_filename = args[0]; 46 | String local_filename = args[1]; 47 | String group_name; 48 | 49 | try 50 | { 51 | ClientGlobal.init(conf_filename); 52 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 53 | System.out.println("charset=" + ClientGlobal.g_charset); 54 | 55 | String file_id; 56 | 57 | TrackerClient tracker = new TrackerClient(); 58 | TrackerServer trackerServer = tracker.getConnection(); 59 | 60 | StorageServer storageServer = null; 61 | /* 62 | storageServer = tracker.getStoreStorage(trackerServer); 63 | if (storageServer == null) 64 | { 65 | System.out.println("getStoreStorage fail, error code: " + tracker.getErrorCode()); 66 | return; 67 | } 68 | */ 69 | StorageClient1 client = new StorageClient1(trackerServer, storageServer); 70 | byte[] file_buff; 71 | NameValuePair[] meta_list; 72 | String master_file_id; 73 | String prefix_name; 74 | String file_ext_name; 75 | String slave_file_id; 76 | String generated_slave_file_id; 77 | int errno; 78 | 79 | group_name = "group1"; 80 | StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name); 81 | if (storageServers == null) 82 | { 83 | System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode()); 84 | } 85 | else 86 | { 87 | System.err.println("store storage servers count: " + storageServers.length); 88 | for (int k=0; k 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) 261 | { 262 | file_ext_name = local_filename.substring(nPos+1); 263 | } 264 | else 265 | { 266 | file_ext_name = null; 267 | } 268 | 269 | file_id = client.upload_file1(null, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); 270 | if (file_id != null) 271 | { 272 | System.out.println("file id: " + file_id); 273 | System.out.println(client.get_file_info1(file_id)); 274 | master_file_id = file_id; 275 | prefix_name = "-part3"; 276 | slave_file_id = client.upload_file1(master_file_id, prefix_name, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list); 277 | if (slave_file_id != null) 278 | { 279 | System.err.println("slave file_id: " + slave_file_id); 280 | generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name); 281 | if (!generated_slave_file_id.equals(slave_file_id)) 282 | { 283 | System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id); 284 | } 285 | } 286 | } 287 | else 288 | { 289 | System.err.println("Upload file fail, error no: " + errno); 290 | } 291 | 292 | storageServer = tracker.getFetchStorage1(trackerServer, file_id); 293 | if (storageServer == null) 294 | { 295 | System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode()); 296 | return; 297 | } 298 | 299 | /* for test only */ 300 | System.out.println("active test to storage server: " + ProtoCommon.activeTest(storageServer.getSocket())); 301 | storageServer.close(); 302 | 303 | /* for test only */ 304 | System.out.println("active test to tracker server: " + ProtoCommon.activeTest(trackerServer.getSocket())); 305 | 306 | trackerServer.close(); 307 | } 308 | catch(Exception ex) 309 | { 310 | ex.printStackTrace(); 311 | } 312 | } 313 | } 314 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/TestLoad.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | **/ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.net.*; 13 | import java.util.*; 14 | import fileserver.dfsserver.org.csource.common.*; 15 | import fileserver.dfsserver.org.csource.fastdfs.*; 16 | 17 | /** 18 | * load test class 19 | * @author Happy Fish / YuQing 20 | * @version Version 1.11 21 | */ 22 | public class TestLoad 23 | { 24 | public static java.util.concurrent.ConcurrentLinkedQueue file_ids; 25 | public static int total_download_count = 0; 26 | public static int success_download_count = 0; 27 | public static int fail_download_count = 0; 28 | public static int total_upload_count = 0; 29 | public static int success_upload_count = 0; 30 | public static int upload_thread_count = 0; 31 | 32 | /** 33 | * discard file content callback class when download file 34 | * @author Happy Fish / YuQing 35 | * @version Version 1.0 36 | */ 37 | public static class DownloadFileDiscard implements DownloadCallback 38 | { 39 | public DownloadFileDiscard() 40 | { 41 | } 42 | 43 | public int recv(long file_size, byte[] data, int bytes) 44 | { 45 | return 0; 46 | } 47 | } 48 | 49 | /** 50 | * file uploader 51 | * @author Happy Fish / YuQing 52 | * @version Version 1.0 53 | */ 54 | public static class Uploader 55 | { 56 | public TrackerClient tracker; 57 | public TrackerServer trackerServer; 58 | 59 | public Uploader() throws Exception 60 | { 61 | this.tracker = new TrackerClient(); 62 | this.trackerServer = tracker.getConnection(); 63 | } 64 | 65 | public int uploadFile() throws Exception 66 | { 67 | StorageServer storageServer = null; 68 | StorageClient1 client = new StorageClient1(trackerServer, storageServer); 69 | byte[] file_buff; 70 | String file_id; 71 | 72 | file_buff = new byte[2 * 1024]; 73 | Arrays.fill(file_buff, (byte)65); 74 | 75 | try 76 | { 77 | file_id = client.upload_file1(file_buff, "txt", null); 78 | if (file_id == null) 79 | { 80 | System.out.println("upload file fail, error code: " + client.getErrorCode()); 81 | return -1; 82 | } 83 | 84 | TestLoad.file_ids.offer(file_id); 85 | return 0; 86 | } 87 | catch(Exception ex) 88 | { 89 | System.out.println("upload file fail, error mesg: " + ex.getMessage()); 90 | return -1; 91 | } 92 | } 93 | } 94 | 95 | /** 96 | * file downloader 97 | * @author Happy Fish / YuQing 98 | * @version Version 1.0 99 | */ 100 | public static class Downloader 101 | { 102 | public TrackerClient tracker; 103 | public TrackerServer trackerServer; 104 | public DownloadFileDiscard callback; 105 | 106 | public Downloader() throws Exception 107 | { 108 | this.tracker = new TrackerClient(); 109 | this.trackerServer = tracker.getConnection(); 110 | this.callback = new DownloadFileDiscard(); 111 | } 112 | 113 | public int downloadFile(String file_id) throws Exception 114 | { 115 | int errno; 116 | StorageServer storageServer = null; 117 | StorageClient1 client = new StorageClient1(trackerServer, storageServer); 118 | 119 | try 120 | { 121 | errno = client.download_file1(file_id, this.callback); 122 | if (errno != 0) 123 | { 124 | System.out.println("Download file fail, file_id: " + file_id + ", error no: " + errno); 125 | } 126 | return errno; 127 | } 128 | catch(Exception ex) 129 | { 130 | System.out.println("Download file fail, error mesg: " + ex.getMessage()); 131 | return -1; 132 | } 133 | } 134 | } 135 | 136 | /** 137 | * upload file thread 138 | * @author Happy Fish / YuQing 139 | * @version Version 1.0 140 | */ 141 | public static class UploadThread extends Thread 142 | { 143 | private int thread_index; 144 | 145 | public UploadThread(int index) 146 | { 147 | this.thread_index = index; 148 | } 149 | 150 | public void run() 151 | { 152 | try 153 | { 154 | TestLoad.upload_thread_count++; 155 | Uploader uploader = new Uploader(); 156 | 157 | System.out.println("upload thread " + this.thread_index + " start"); 158 | 159 | for (int i=0; i<50000; i++) 160 | { 161 | TestLoad.total_upload_count++; 162 | if (uploader.uploadFile() == 0) 163 | { 164 | TestLoad.success_upload_count++; 165 | } 166 | } 167 | } 168 | catch(Exception ex) 169 | { 170 | ex.printStackTrace(); 171 | } 172 | finally 173 | { 174 | TestLoad.upload_thread_count--; 175 | } 176 | 177 | System.out.println("upload thread " + this.thread_index 178 | + " exit, total_upload_count: " + TestLoad.total_upload_count 179 | + ", success_upload_count: " + TestLoad.success_upload_count 180 | + ", total_download_count: " + TestLoad.total_download_count 181 | + ", success_download_count: " + TestLoad.success_download_count); 182 | } 183 | } 184 | 185 | /** 186 | * download file thread 187 | * @author Happy Fish / YuQing 188 | * @version Version 1.0 189 | */ 190 | public static class DownloadThread extends Thread 191 | { 192 | private int thread_index; 193 | private static Integer counter_lock = new Integer(0); 194 | 195 | public DownloadThread(int index) 196 | { 197 | this.thread_index = index; 198 | } 199 | 200 | public void run() 201 | { 202 | try 203 | { 204 | String file_id; 205 | Downloader downloader = new Downloader(); 206 | 207 | System.out.println("download thread " + this.thread_index + " start"); 208 | 209 | file_id = ""; 210 | while (TestLoad.upload_thread_count != 0 || file_id != null) 211 | { 212 | file_id = (String)TestLoad.file_ids.poll(); 213 | if (file_id == null) 214 | { 215 | Thread.sleep(10); 216 | continue; 217 | } 218 | 219 | synchronized (this.counter_lock) 220 | { 221 | TestLoad.total_download_count++; 222 | } 223 | if (downloader.downloadFile(file_id) == 0) 224 | { 225 | synchronized (this.counter_lock) 226 | { 227 | TestLoad.success_download_count++; 228 | } 229 | } 230 | else 231 | { 232 | TestLoad.fail_download_count++; 233 | } 234 | } 235 | 236 | for (int i=0; i<3 && TestLoad.total_download_count < TestLoad.total_upload_count; i++) 237 | { 238 | file_id = (String)TestLoad.file_ids.poll(); 239 | if (file_id == null) 240 | { 241 | Thread.sleep(10); 242 | continue; 243 | } 244 | 245 | synchronized (this.counter_lock) 246 | { 247 | TestLoad.total_download_count++; 248 | } 249 | if (downloader.downloadFile(file_id) == 0) 250 | { 251 | synchronized (this.counter_lock) 252 | { 253 | TestLoad.success_download_count++; 254 | } 255 | } 256 | else 257 | { 258 | TestLoad.fail_download_count++; 259 | } 260 | } 261 | } 262 | catch(Exception ex) 263 | { 264 | ex.printStackTrace(); 265 | } 266 | 267 | System.out.println("download thread " + this.thread_index 268 | + " exit, total_download_count: " + TestLoad.total_download_count 269 | + ", success_download_count: " + TestLoad.success_download_count 270 | + ", fail_download_count: " + TestLoad.fail_download_count); 271 | } 272 | } 273 | 274 | private TestLoad() 275 | { 276 | } 277 | 278 | /** 279 | * entry point 280 | * @param args comand arguments 281 | *
  • args[0]: config filename
282 | */ 283 | public static void main(String args[]) 284 | { 285 | if (args.length < 1) 286 | { 287 | System.out.println("Error: Must have 1 parameter: config filename"); 288 | return; 289 | } 290 | 291 | System.out.println("java.version=" + System.getProperty("java.version")); 292 | 293 | try 294 | { 295 | ClientGlobal.init(args[0]); 296 | System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms"); 297 | System.out.println("charset=" + ClientGlobal.g_charset); 298 | 299 | file_ids = new java.util.concurrent.ConcurrentLinkedQueue(); 300 | 301 | for (int i=0; i<10; i++) 302 | { 303 | (new UploadThread(i)).start(); 304 | } 305 | 306 | for (int i=0; i<20; i++) 307 | { 308 | (new DownloadThread(i)).start(); 309 | } 310 | } 311 | catch(Exception ex) 312 | { 313 | ex.printStackTrace(); 314 | } 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /JServer/src/fileserver/dfsserver/org/csource/fastdfs/test/UploadLocalFileSender.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2008 Happy Fish / YuQing 3 | * 4 | * FastDFS Java Client may be copied only under the terms of the GNU Lesser 5 | * General Public License (LGPL). 6 | * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. 7 | */ 8 | 9 | package fileserver.dfsserver.org.csource.fastdfs.test; 10 | 11 | import java.io.*; 12 | import java.util.*; 13 | import java.net.*; 14 | import fileserver.dfsserver.org.csource.fastdfs.*; 15 | 16 | /** 17 | * upload file callback class, local file sender 18 | * @author Happy Fish / YuQing 19 | * @version Version 1.0 20 | */ 21 | public class UploadLocalFileSender implements UploadCallback 22 | { 23 | private String local_filename; 24 | 25 | public UploadLocalFileSender(String szLocalFilename) 26 | { 27 | this.local_filename = szLocalFilename; 28 | } 29 | 30 | /** 31 | * send file content callback function, be called only once when the file uploaded 32 | * @param out output stream for writing file content 33 | * @return 0 success, return none zero(errno) if fail 34 | */ 35 | public int send(OutputStream out) throws IOException 36 | { 37 | FileInputStream fis; 38 | int readBytes; 39 | byte[] buff = new byte[256 * 1024]; 40 | 41 | fis = new FileInputStream(this.local_filename); 42 | try 43 | { 44 | while ((readBytes=fis.read(buff)) >= 0) 45 | { 46 | if (readBytes == 0) 47 | { 48 | continue; 49 | } 50 | 51 | out.write(buff, 0, readBytes); 52 | } 53 | } 54 | finally 55 | { 56 | fis.close(); 57 | } 58 | 59 | return 0; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /JServer/src/loginserver/LoginServer.java: -------------------------------------------------------------------------------- 1 | package loginserver; 2 | 3 | import base.config.ConfigReader; 4 | import base.config.ConfigUtil; 5 | import base.pdu.PduDecoder; 6 | import base.pdu.PduEncoder; 7 | import base.pdu.PduHandler; 8 | import io.netty.bootstrap.ServerBootstrap; 9 | import io.netty.channel.ChannelFuture; 10 | import io.netty.channel.ChannelInitializer; 11 | import io.netty.channel.ChannelOption; 12 | import io.netty.channel.EventLoopGroup; 13 | import io.netty.channel.nio.NioEventLoopGroup; 14 | import io.netty.channel.socket.SocketChannel; 15 | import io.netty.channel.socket.nio.NioServerSocketChannel; 16 | import io.netty.handler.logging.LogLevel; 17 | import io.netty.handler.logging.LoggingHandler; 18 | import loginserver.handler.channel.CLoginInBaseHandler; 19 | import loginserver.handler.channel.CLoginOutBaseHandler; 20 | import org.apache.log4j.Logger; 21 | import org.apache.log4j.PropertyConfigurator; 22 | 23 | import java.util.HashMap; 24 | 25 | /** 26 | * Created by Administrator on 2017/5/15 0015. 27 | */ 28 | public class LoginServer { 29 | 30 | private HashMap handlerHashMap = new HashMap<>(); 31 | private static Logger logger = Logger.getLogger(LoginServer.class); 32 | public LoginServer(){ 33 | initHandlerMap(this.handlerHashMap); 34 | initLog(); 35 | } 36 | public void bind(int clientListenPort) throws Exception { 37 | logger.debug("负载均衡服务器:启动客户端监听,端口号:"+clientListenPort); 38 | // 配置服务端的NIO线程组 39 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 40 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 41 | try { 42 | ServerBootstrap bootstrap = new ServerBootstrap(); 43 | bootstrap.group(bossGroup, workerGroup) 44 | .channel(NioServerSocketChannel.class) 45 | .option(ChannelOption.SO_BACKLOG, 100) 46 | .handler(new LoggingHandler(LogLevel.INFO)) 47 | .childHandler(new ChannelInitializer() { 48 | @Override 49 | public void initChannel(SocketChannel ch) { 50 | // 注册相应的handler和encoder和decoder 51 | ch.pipeline().addLast(new PduDecoder()); 52 | ch.pipeline().addLast(new PduEncoder()); 53 | ch.pipeline().addLast(new CLoginInBaseHandler(handlerHashMap)); 54 | ch.pipeline().addLast(new CLoginOutBaseHandler()); 55 | } 56 | }); 57 | 58 | // 绑定端口,同步等待成功 59 | ChannelFuture f = bootstrap.bind(clientListenPort).sync(); 60 | // 等待服务端监听端口关闭 61 | f.channel().closeFuture().sync(); 62 | } finally { 63 | // 优雅退出,释放线程池资源 64 | bossGroup.shutdownGracefully(); 65 | workerGroup.shutdownGracefully(); 66 | } 67 | } 68 | 69 | /** 70 | * 初始化业务handlerMap 71 | * @return 72 | */ 73 | private HashMap initHandlerMap(HashMap handlerHashMap){ 74 | 75 | return handlerHashMap; 76 | } 77 | 78 | private void initLog(){ 79 | PropertyConfigurator.configure("config/log4j.properties"); 80 | } 81 | 82 | public static void main(String[] args) throws Exception { 83 | // 用于监听客户端的端口,从配置文件中读取(10010是默认值) 84 | int clientListenPort = 10010; 85 | // 配置文件名字 86 | String fileName = "LoginServer.properties"; 87 | /* 解析配置文件 */ 88 | String relativePath = "\\src\\loginserver\\"; 89 | String fullPath = ConfigUtil.getAbsolateConfPath(relativePath, fileName); 90 | ConfigReader configReader = new ConfigReader(fullPath); 91 | // 获取配置文件中的端口号 92 | clientListenPort = configReader.getInt("ClientPort"); 93 | /* 初始化LoginServer服务器*/ 94 | LoginServer server = new LoginServer(); 95 | server.bind(clientListenPort); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /JServer/src/loginserver/LoginServer.properties: -------------------------------------------------------------------------------- 1 | # config format spec 2 | # this is a commet 3 | ClientListenIP=0.0.0.0 4 | ClientPort=8008 5 | HttpListenIP=0.0.0.0 6 | HttpPort=8080 7 | MsgServerListenIP=0.0.0.0 8 | MsgServerPort=8100 9 | msfs=http://127.0.0.1:8700/ 10 | discovery=http://127.0.0.1/api/discovery 11 | -------------------------------------------------------------------------------- /JServer/src/loginserver/conf/ClientType.java: -------------------------------------------------------------------------------- 1 | package loginserver.conf; 2 | 3 | /** 4 | * Created by Administrator on 2017/5/15 0015. 5 | */ 6 | public enum ClientType { 7 | LOGIN_CONN_TYPE_CLIENT ,LOGIN_CONN_TYPE_MSG_SERV; 8 | } 9 | -------------------------------------------------------------------------------- /JServer/src/loginserver/conf/LoginMsgType.java: -------------------------------------------------------------------------------- 1 | package loginserver.conf; 2 | 3 | /** 4 | * Created by muhong on 2016/11/21. 5 | */ 6 | public class LoginMsgType { 7 | public static int LOIGN_REQ = 1; 8 | public static int LOGIN_RESP = 2; 9 | public static int HEARTBEAT_REQ = 3; 10 | public static int HEARBEAR_RESP = 4; 11 | public static int MSG_SERVER_REQ = 5; 12 | public static int MSG_SERVER_RESP = 6; 13 | } 14 | -------------------------------------------------------------------------------- /JServer/src/loginserver/handler/channel/CLoginInBaseHandler.java: -------------------------------------------------------------------------------- 1 | package loginserver.handler.channel; 2 | 3 | import base.pdu.PduBase; 4 | import base.pdu.PduHandler; 5 | import base.pdu.PduHeader; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.channel.ChannelInboundHandlerAdapter; 8 | import org.apache.log4j.Logger; 9 | 10 | import java.util.HashMap; 11 | 12 | /** 13 | * 自定义的netty管道的handler 14 | * 初始化业务的handler,并根据包体的类型选择相应的handler进行处理 15 | * Created by Administrator on 2016/12/8 0008. 16 | */ 17 | public class CLoginInBaseHandler extends ChannelInboundHandlerAdapter { 18 | private static Logger logger = Logger.getLogger(CLoginInBaseHandler.class); 19 | private HashMap handlerMap; 20 | 21 | public CLoginInBaseHandler(HashMap handlerMap){ 22 | // 初始化HandlerMap 23 | this.handlerMap = handlerMap; 24 | } 25 | 26 | @Override 27 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 28 | 29 | } 30 | 31 | @Override 32 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 33 | // 根据commandID找到handler,并处理pdu 34 | PduBase pduBase = (PduBase) msg; 35 | PduHeader header = pduBase.getHeader(); 36 | PduHandler handler = handlerMap.get((int)header.getCommandId()); 37 | if(handler != null){ 38 | handler.handlePdu(pduBase); 39 | }else { 40 | logger.error("没有找到合适的handler"); 41 | } 42 | } 43 | 44 | @Override 45 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 46 | ctx.close(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /JServer/src/loginserver/handler/channel/CLoginOutBaseHandler.java: -------------------------------------------------------------------------------- 1 | package loginserver.handler.channel; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelOutboundHandlerAdapter; 5 | import io.netty.channel.ChannelPromise; 6 | 7 | /** 8 | * Created by Administrator on 2016/12/8 0008. 9 | */ 10 | public class CLoginOutBaseHandler extends ChannelOutboundHandlerAdapter { 11 | 12 | @Override 13 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { 14 | super.write(ctx, msg, promise); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /JServer/src/loginserver/test/Test1.java: -------------------------------------------------------------------------------- 1 | package loginserver.test; 2 | 3 | import base.config.ConfigReader; 4 | import base.config.ConfigUtil; 5 | import org.apache.log4j.PropertyConfigurator; 6 | 7 | /** 8 | * Created by Administrator on 2017/5/15 0015. 9 | */ 10 | public class Test1 { 11 | public static void main(String[] args) { 12 | Test1.initLog(); 13 | System.out.println("配置文件测试"); 14 | String fileName = "LoginServer.properties"; 15 | String relativePath = "\\src\\loginserver\\"; 16 | String fullPath = ConfigUtil.getAbsolateConfPath(relativePath, fileName); 17 | System.out.println(fullPath); 18 | ConfigReader configReader = new ConfigReader(fullPath); 19 | 20 | System.out.println(configReader.getString("ClientListenIP")); 21 | } 22 | 23 | public static void initLog(){ 24 | PropertyConfigurator.configure("config/log4j.properties"); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /JServer/src/loginserver/vo/MsgServerInfo.java: -------------------------------------------------------------------------------- 1 | package loginserver.vo; 2 | 3 | /** 4 | * Created by Administrator on 2017/5/15 0015. 5 | */ 6 | public class MsgServerInfo { 7 | private String ipAddr1; // 电信ip 8 | private String ipAddr2; // 网通ip 9 | private int port; 10 | private int maxConnCnt; 11 | private int curConnCnt; 12 | private String hostname; 13 | 14 | public String getIpAddr1() { 15 | return ipAddr1; 16 | } 17 | 18 | public void setIpAddr1(String ipAddr1) { 19 | this.ipAddr1 = ipAddr1; 20 | } 21 | 22 | public int getPort() { 23 | return port; 24 | } 25 | 26 | public void setPort(int port) { 27 | this.port = port; 28 | } 29 | 30 | public String getIpAddr2() { 31 | return ipAddr2; 32 | } 33 | 34 | public void setIpAddr2(String ipAddr2) { 35 | this.ipAddr2 = ipAddr2; 36 | } 37 | 38 | public int getMaxConnCnt() { 39 | return maxConnCnt; 40 | } 41 | 42 | public void setMaxConnCnt(int maxConnCnt) { 43 | this.maxConnCnt = maxConnCnt; 44 | } 45 | 46 | public int getCurConnCnt() { 47 | return curConnCnt; 48 | } 49 | 50 | public void setCurConnCnt(int curConnCnt) { 51 | this.curConnCnt = curConnCnt; 52 | } 53 | 54 | public String getHostname() { 55 | return hostname; 56 | } 57 | 58 | public void setHostname(String hostname) { 59 | this.hostname = hostname; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /JServer/src/msgserver/MsgServer.java: -------------------------------------------------------------------------------- 1 | package msgserver; 2 | 3 | import base.config.ConfigReader; 4 | import base.config.ConfigUtil; 5 | import base.pdu.PduDecoder; 6 | import base.pdu.PduEncoder; 7 | import base.pdu.PduHandler; 8 | import io.netty.bootstrap.ServerBootstrap; 9 | import io.netty.channel.ChannelFuture; 10 | import io.netty.channel.ChannelInitializer; 11 | import io.netty.channel.ChannelOption; 12 | import io.netty.channel.EventLoopGroup; 13 | import io.netty.channel.nio.NioEventLoopGroup; 14 | import io.netty.channel.socket.SocketChannel; 15 | import io.netty.channel.socket.nio.NioServerSocketChannel; 16 | import io.netty.handler.logging.LogLevel; 17 | import io.netty.handler.logging.LoggingHandler; 18 | import msgserver.global.MsgGlobal; 19 | import msgserver.handler.channel.CMsgServerInBaseHandler; 20 | import msgserver.handler.channel.CMsgServerOutBaseHandler; 21 | import org.apache.log4j.Logger; 22 | import org.apache.log4j.PropertyConfigurator; 23 | 24 | import java.util.HashMap; 25 | 26 | /** 27 | * Created by Administrator on 2017/5/15 0015. 28 | */ 29 | public class MsgServer { 30 | 31 | private static Logger logger = Logger.getLogger(MsgServer.class); 32 | 33 | public MsgServer(){ 34 | // 完成服务器的初始化工作 35 | initHandlerMap(); 36 | initLog(); 37 | } 38 | 39 | public void bind(int clientListenPort) throws Exception { 40 | logger.debug("消息服务器:启动客户端监听,端口号:"+clientListenPort); 41 | // 参考netty主从多线程模型 42 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 43 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 44 | try { 45 | ServerBootstrap bootstrap = new ServerBootstrap(); 46 | bootstrap.group(bossGroup, workerGroup) 47 | .channel(NioServerSocketChannel.class) 48 | .option(ChannelOption.SO_BACKLOG, 100) 49 | .handler(new LoggingHandler(LogLevel.INFO)) 50 | .childHandler(new ChannelInitializer() { 51 | @Override 52 | public void initChannel(SocketChannel ch) { 53 | logger.debug("有新的客户端连接进来"); 54 | ch.pipeline().addLast(new PduDecoder()); 55 | ch.pipeline().addLast(new PduEncoder()); 56 | ch.pipeline().addLast(new CMsgServerInBaseHandler()); 57 | ch.pipeline().addLast(new CMsgServerOutBaseHandler()); 58 | } 59 | }); 60 | ChannelFuture f = bootstrap.bind(clientListenPort).sync(); 61 | f.channel().closeFuture().sync(); 62 | } finally { 63 | // 优雅退出,释放线程池资源 64 | bossGroup.shutdownGracefully(); 65 | workerGroup.shutdownGracefully(); 66 | } 67 | } 68 | 69 | /** 70 | * 初始化handlerMap 71 | * 不同的通信数据报文对应不同的handler 72 | * @return 73 | */ 74 | private HashMap initHandlerMap(){ 75 | return MsgGlobal.handlerMap; 76 | } 77 | 78 | /** 79 | * 初始化log4j日志配置 80 | */ 81 | private void initLog(){ 82 | PropertyConfigurator.configure("config/log4j.properties"); 83 | } 84 | 85 | public static void main(String[] args) throws Exception { 86 | // 客户端监听端口,配置文件读取(默认10011) 87 | int clientListenPort = 10011; 88 | // 解析配置文件 89 | String fileName = "MsgServer.properties"; 90 | String relativePath = "\\src\\msgserver\\"; 91 | String fullPath = ConfigUtil.getAbsolateConfPath(relativePath, fileName); 92 | ConfigReader configReader = new ConfigReader(fullPath); 93 | // 获取配置文件中的端口号 94 | clientListenPort = configReader.getInt("ListenPort"); 95 | MsgServer server = new MsgServer(); 96 | server.bind(clientListenPort); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /JServer/src/msgserver/MsgServer.properties: -------------------------------------------------------------------------------- 1 | ListenIP=0.0.0.0 2 | ListenPort=8000 3 | 4 | ConcurrentDBConnCnt=1 5 | DBServerIP1=127.0.0.1 6 | DBServerPort1=10600 7 | #DBServerIP2=127.0.0.1 8 | #DBServerPort2=10600 9 | 10 | LoginServerIP1=localhost 11 | LoginServerPort1=8100 12 | #LoginServerIP2=localhost 13 | #LoginServerPort2=8101 14 | 15 | SessionServerIP1=localhost 16 | SessionServerPort1=8200 17 | #RouteServerIP2=localhost 18 | #RouteServerPort2=8201 19 | 20 | PushServerIP1=localhost 21 | PushServerPort1=8500 22 | 23 | FileServerIP1=localhost 24 | FileServerPort1=8600 25 | 26 | #FileServerIP2=localhost 27 | #FileServerPort2=8601 28 | 29 | IpAddr1=localhost 30 | IpAddr2=localhost 31 | MaxConnCnt=100000 32 | # AES key 33 | aesKey=12345678901234567890123456789012 34 | -------------------------------------------------------------------------------- /JServer/src/msgserver/conf/MsgPduType.java: -------------------------------------------------------------------------------- 1 | package msgserver.conf; 2 | 3 | /** 4 | * 和消息服务器相关的网络报文的类型 5 | * Created by muhong on 2016/11/21. 6 | */ 7 | public class MsgPduType { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /JServer/src/msgserver/global/MsgGlobal.java: -------------------------------------------------------------------------------- 1 | package msgserver.global; 2 | 3 | 4 | import base.pdu.PduHandler; 5 | 6 | import java.util.HashMap; 7 | 8 | /** 9 | * Created by Administrator on 2017/4/14 0014. 10 | */ 11 | public class MsgGlobal { 12 | public static HashMap handlerMap = new HashMap<>(); 13 | } 14 | -------------------------------------------------------------------------------- /JServer/src/msgserver/handler/channel/CMsgServerInBaseHandler.java: -------------------------------------------------------------------------------- 1 | package msgserver.handler.channel; 2 | 3 | 4 | import base.pdu.PduBase; 5 | import base.pdu.PduHandler; 6 | import base.pdu.PduHeader; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.channel.ChannelInboundHandlerAdapter; 9 | import msgserver.global.MsgGlobal; 10 | import org.apache.log4j.Logger; 11 | 12 | /** 13 | * 消息接入的handler 14 | * Created by Administrator on 2016/12/8 0008. 15 | */ 16 | public class CMsgServerInBaseHandler extends ChannelInboundHandlerAdapter { 17 | private static Logger logger = Logger.getLogger(CMsgServerInBaseHandler.class); 18 | 19 | public CMsgServerInBaseHandler(){ 20 | // 初始化HandlerMap 21 | 22 | } 23 | 24 | @Override 25 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 26 | super.channelActive(ctx); 27 | } 28 | 29 | @Override 30 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 31 | // msg是经过PduDecoder从字节流中封装成的PduBase包 32 | PduBase pduBase = (PduBase) msg; 33 | PduHeader header = pduBase.getHeader(); 34 | PduHandler handler = MsgGlobal.handlerMap.get((int)header.getCommandId()); 35 | if(handler != null){ 36 | handler.handlePdu(pduBase); 37 | }else { 38 | logger.error("没有找到合适的handler"); 39 | } 40 | } 41 | 42 | @Override 43 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 44 | ctx.close(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /JServer/src/msgserver/handler/channel/CMsgServerOutBaseHandler.java: -------------------------------------------------------------------------------- 1 | package msgserver.handler.channel; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelOutboundHandlerAdapter; 5 | import io.netty.channel.ChannelPromise; 6 | 7 | /** 8 | * Created by Administrator on 2016/12/8 0008. 9 | */ 10 | public class CMsgServerOutBaseHandler extends ChannelOutboundHandlerAdapter { 11 | @Override 12 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { 13 | super.write(ctx, msg, promise); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /JServer/src/sessionserver/SessionServer.java: -------------------------------------------------------------------------------- 1 | package sessionserver; 2 | 3 | /** 4 | * Created by Administrator on 2017/5/15 0015. 5 | */ 6 | public class SessionServer { 7 | } 8 | -------------------------------------------------------------------------------- /JServer/src/sessionserver/SessionServer.properties: -------------------------------------------------------------------------------- 1 | ListenIP=0.0.0.0 # Listening IP 2 | ListenMsgPort=8200 # Listening Port for MsgServer 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IMJavaSparrow 2 | Java即时通讯软件,本项目取名IMJavaSparrow的原因是,IM是即时通讯的意思、Java是开发语言、Sparrow是麻雀的意思(有句俗语是麻雀虽小五脏俱全,这种软件常用于计算机教育中,可以让学生更好的理解计算机的一些概念和原理),所以项目名称也表达了本项目的意义所在,希望使用Java做一个即时通讯的软件,这个软件不用特别庞大,但是一定要包含一定的核心功能。 3 | 4 | 本项目启发于开源即时通讯框架TeamTalk,编写此项目的原因主要有两点: 5 | 1. 随着Java语言的流行,越来越多的开发者使用Java开发服务器端程序,虽然Java提供了一些高性能的网络库,但是并没有一个完整的开源的即时通讯软件,这使得Java初级开发者着手即时通讯软件开发的难度大,所以为了能是Java初级开发者能更好的理解基于Java的即时通讯的开发,本人仿照了开源即时通讯框架TeamTalk的设计思路,完成该项目的开发。 6 | 2. 着手该项目同时也是工作上的需求,由于本人目前的工作任务是要使用Java设计一个高性能的即时通讯服务器,所以将项目中的不涉及业务的代码抽离出来开源,希望能帮到那些想使用Java进行即时通讯开发的开发者。 7 | 8 | 9 | 代码已导入,目前只包含了server,server主要使用了如下的jar包: 10 | 11 | 1. 高性能网络框架netty 12 | 2. mybatis数据库访问 13 | 3. log4j日志记录 14 | 4. protobuf协议编码 15 | 5. fastDFS客户端,连接fastDFS 16 | 17 | server中已经完成了各项配置,并完成了协议的编码解码等功能,后续将继续完善! 18 | 19 | 我的技术博客网站:http://47777205.com/ ,该网站会不定时更新JDK源码、Java框架源码分析相关的文档。 20 | --------------------------------------------------------------------------------