├── codec.cpp ├── codec.h ├── common.h ├── filesync.pro ├── filesync.pro.user ├── filesync.pro.user.3c5f4f3 ├── filesync.pro.user.dc6fb4f ├── hehe ├── main.cpp ├── md5.h ├── parseconfig.cpp ├── parseconfig.h ├── protobuf ├── compile_proto.sh ├── filesync.pb.cc ├── filesync.pb.h └── filesync.proto ├── rsync.cpp ├── rsync.h ├── socket.cpp ├── socket.h ├── str_tool.cpp ├── str_tool.h ├── syncserver.cpp ├── syncserver.h ├── sysutil.cpp ├── sysutil.h └── test ├── echo.h ├── filesendtest.cpp ├── muduo_test.cpp ├── oobServer.cpp ├── parsetest.cpp ├── prototest.cpp ├── rsynctest.cpp └── socketTest.cpp /codec.cpp: -------------------------------------------------------------------------------- 1 | #include "codec.h" 2 | #include 3 | 4 | #include 5 | #include // adler32 6 | #include // htonl, ntohl 7 | using namespace std; 8 | Codec::Codec() 9 | { 10 | 11 | } 12 | 13 | int asInt32(const char* buf) 14 | { 15 | int be32 = 0; 16 | ::memcpy(&be32, buf, sizeof(be32)); 17 | return ::ntohl(be32); 18 | } 19 | 20 | /** 21 | * @brief Codec::parse 解析数据 22 | * @param conn 23 | * @param inputBuffer 24 | */ 25 | void Codec::parse(const muduo::net::TcpConnectionPtr &conn, muduo::net::Buffer *inputBuffer) 26 | { 27 | while (inputBuffer->readableBytes() >= kMinMessageLen + kHeaderLen) 28 | { 29 | const int len = inputBuffer->peekInt32(); 30 | if (len < kMinMessageLen) 31 | { 32 | LOG_ERROR<<"parse protobuf error:invalid length"; 33 | break; 34 | } 35 | else if (inputBuffer->readableBytes() >= 36 | muduo::implicit_cast(len + kHeaderLen)) 37 | { 38 | MessagePtr message = parse_aux(inputBuffer->peek()+kHeaderLen,len); 39 | if (message) 40 | { 41 | inputBuffer->retrieve(kHeaderLen+len); 42 | dispatch(conn,message); 43 | } 44 | else 45 | { 46 | LOG_ERROR<<"parse protobuf error"; 47 | break; 48 | } 49 | } 50 | else 51 | { 52 | break; 53 | } 54 | } 55 | } 56 | 57 | /** 58 | * @brief Codec::parse_aux //解析数据得到相应的Message 59 | * @param buf 消息字符串,长度信息已被跳过 60 | * @param len 消息长度 61 | * @return 62 | */ 63 | MessagePtr Codec::parse_aux(const char* buf, int len) 64 | { 65 | MessagePtr message; 66 | 67 | // check sum 68 | int expectedCheckSum = asInt32(buf + len - kHeaderLen); 69 | int checkSum = static_cast( 70 | ::adler32(1, 71 | reinterpret_cast(buf), 72 | static_cast(len - kHeaderLen))); 73 | if (checkSum == expectedCheckSum) 74 | { 75 | // get message type name 76 | int nameLen = asInt32(buf); 77 | if (nameLen >= 2 && nameLen <= len - 2*kHeaderLen) 78 | { 79 | std::string typeName(buf + kHeaderLen, buf + kHeaderLen + nameLen - 1); 80 | // create message object 81 | message.reset(createMessage(typeName)); 82 | if (message) 83 | { 84 | // parse from buffer 85 | const char* data = buf + kHeaderLen + nameLen; 86 | int dataLen = len - nameLen - 2*kHeaderLen; 87 | if (!message->ParseFromArray(data, dataLen)) 88 | { 89 | LOG_ERROR<<"ParseError"; 90 | } 91 | } 92 | else 93 | { 94 | LOG_ERROR<<"UnownMessageType"; 95 | } 96 | } 97 | else 98 | { 99 | LOG_ERROR<<"InvalidNameLen"; 100 | } 101 | } 102 | else 103 | { 104 | LOG_ERROR<<"CheckSumError"; 105 | } 106 | 107 | return message; 108 | } 109 | 110 | void Codec::dispatch(const muduo::net::TcpConnectionPtr& conn, MessagePtr message) 111 | { 112 | auto it = callbackMap.find(message->GetDescriptor()); 113 | if (it != callbackMap.end()) 114 | { 115 | it->second->onMessage(conn, message); 116 | } 117 | else 118 | LOG_ERROR<GetTypeName()<<"didn't register callback"; 119 | } 120 | 121 | /** 122 | * @brief Codec::encode 将要发送的信息打包 123 | * @param message 要发送的信息 124 | * @return 如果message.AppendToString失败则返回空字符串 125 | */ 126 | string Codec::enCode(const google::protobuf::Message& message) 127 | { 128 | string result; 129 | 130 | result.resize(kHeaderLen); 131 | 132 | const string& typeName = message.GetTypeName(); 133 | int32_t nameLen = static_cast(typeName.size()+1); 134 | int32_t be32 = ::htonl(nameLen); 135 | result.append(reinterpret_cast(&be32), sizeof be32); 136 | result.append(typeName.c_str(), nameLen); 137 | bool succeed = message.AppendToString(&result); 138 | 139 | if (succeed) 140 | { 141 | const char* begin = result.c_str() + kHeaderLen; 142 | int32_t checkSum = adler32(1, reinterpret_cast(begin), result.size()-kHeaderLen); 143 | int32_t be32 = ::htonl(checkSum); 144 | result.append(reinterpret_cast(&be32), sizeof be32); 145 | 146 | int32_t len = ::htonl(result.size() - kHeaderLen); 147 | std::copy(reinterpret_cast(&len), 148 | reinterpret_cast(&len) + sizeof len, 149 | result.begin()); 150 | } 151 | else 152 | { 153 | result.clear(); 154 | } 155 | 156 | return result; 157 | } 158 | 159 | 160 | google::protobuf::Message* Codec::createMessage(const std::string& typeName) 161 | { 162 | google::protobuf::Message* message = NULL; 163 | const google::protobuf::Descriptor* descriptor = 164 | google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(typeName); 165 | if (descriptor) 166 | { 167 | const google::protobuf::Message* prototype = 168 | google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor); 169 | if (prototype) 170 | { 171 | message = prototype->New(); 172 | } 173 | } 174 | return message; 175 | } 176 | -------------------------------------------------------------------------------- /codec.h: -------------------------------------------------------------------------------- 1 | #ifndef CODEC_H 2 | #define CODEC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | //Message* 创建后需要释放,用智能指针管理 15 | typedef std::shared_ptr MessagePtr; 16 | 17 | class Callback 18 | { 19 | public: 20 | virtual ~Callback() {} 21 | virtual void onMessage(const muduo::net::TcpConnectionPtr& conn, 22 | const MessagePtr& message) const = 0; 23 | }; 24 | 25 | template 26 | /** 27 | * @brief The CallbackT class 利用模板保存不同类型message的回调函数,继承自一个非目标类便于map保存 28 | */ 29 | class CallbackT : public Callback 30 | { 31 | public: 32 | typedef std::function& message)> ProtobufMessageTCallback; 34 | 35 | CallbackT(const ProtobufMessageTCallback& callback) 36 | : callback_(callback) 37 | { 38 | } 39 | 40 | virtual void onMessage(const muduo::net::TcpConnectionPtr& conn, 41 | const MessagePtr& message) const 42 | { 43 | std::shared_ptr concrete = std::static_pointer_cast(message); 44 | assert(concrete != NULL); 45 | callback_(conn, concrete); 46 | } 47 | private: 48 | ProtobufMessageTCallback callback_; 49 | }; 50 | 51 | 52 | /** 53 | 协议的格式 54 | struct Message{ 55 | int len; 56 | int namelen; 57 | char typename[namelen]; 58 | char protobufData[len-namelen]; 59 | int checkSum; //用adler32产生校验码,根据nameLen,typeName和protobufData产生 60 | }; 61 | */ 62 | class Codec 63 | { 64 | public: 65 | Codec(); 66 | //注册消息类型对应的回调函数 67 | template 68 | void registerCallback(const typename CallbackT::ProtobufMessageTCallback& callback) 69 | { 70 | std::shared_ptr > pd(new CallbackT(callback)); 71 | callbackMap[T::descriptor()] = pd; 72 | } 73 | //将要发送的信息打包,打包方式如上的注释 74 | static std::string enCode(const google::protobuf::Message& message); 75 | //解析数据并执行相应的回调函数 76 | void parse(const muduo::net::TcpConnectionPtr &conn, muduo::net::Buffer *inputBuffer); 77 | private: 78 | static const int kHeaderLen = 4; 79 | static const int kMinMessageLen = 2*kHeaderLen + 2; // nameLen + typeName + checkSum 80 | //根据packege.message来获得相应的Message 81 | google::protobuf::Message* createMessage(const std::string& typeName); 82 | std::unordered_map > callbackMap; 84 | //解析数据得到相应的Message 85 | MessagePtr parse_aux(const char *buf, int len); 86 | //根据消息类型执行相应的回调函数 87 | void dispatch(const muduo::net::TcpConnectionPtr &conn, MessagePtr message); 88 | }; 89 | 90 | #endif // CODEC_H 91 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /** 2 | *@brief:主要的库头文件及一些声明 3 | */ 4 | 5 | #ifndef _COMMON_H 6 | #define _COMMON_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include //套接字编程 18 | #include //地址 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | //'\'后面不要加注释 39 | /** 40 | *FTPD_LOG - 日志宏 41 | *输出日期,时间,日志级别,源码文件,行号,信息 42 | */ 43 | //定义一个日志宏 44 | #define DEBUG 0 45 | #define INFO 1 46 | #define WARN 2 47 | #define ERROR 3 48 | #define CRIT 4 49 | 50 | static const char* LOG_STR[] = { 51 | "DEBUG", 52 | "INFO", 53 | "WARN", 54 | "ERROR", 55 | "CRIT" 56 | }; 57 | 58 | #define CHEN_LOG(level, format, ...) do{ \ 59 | char msg[1024]; \ 60 | char buf[32]; \ 61 | sprintf(msg, format, ##__VA_ARGS__); \ 62 | if (level >= 0) {\ 63 | time_t now = time(NULL); \ 64 | strftime(buf, sizeof(buf), "%H:%M:%S", localtime(&now)); \ 65 | fprintf(stdout, "[%s] [%s] [file:%s] [line:%d] [tid:%ld] %s\n",buf, \ 66 | LOG_STR[level],__FILE__,__LINE__,pthread_self(), msg); \ 67 | fflush (stdout); \ 68 | }\ 69 | if (level >= ERROR) {\ 70 | perror(msg); \ 71 | exit(-1); \ 72 | } \ 73 | } while(0) 74 | 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /filesync.pro: -------------------------------------------------------------------------------- 1 | QT += core 2 | QT -= gui 3 | 4 | CONFIG += c++11 5 | 6 | TARGET = filesync 7 | CONFIG += console 8 | CONFIG -= app_bundle 9 | 10 | LIBS += -L/usr/lib -lprotobuf -lcrypt -lpthread \ 11 | -L/home/chen/Desktop/work/build/release-install/lib -lmuduo_net -lmuduo_base \ 12 | -lz 13 | INCLUDEPATH += /usr/local/include/google/protobuf \ 14 | /home/chen/Desktop/work/build/release-install/include 15 | 16 | TEMPLATE = app 17 | 18 | SOURCES += main.cpp \ 19 | socket.cpp \ 20 | sysutil.cpp \ 21 | test/socketTest.cpp \ 22 | test/filesendtest.cpp \ 23 | test/prototest.cpp \ 24 | test/muduo_test.cpp \ 25 | syncserver.cpp \ 26 | protobuf/filesync.pb.cc \ 27 | codec.cpp \ 28 | parseconfig.cpp \ 29 | str_tool.cpp \ 30 | test/parsetest.cpp \ 31 | rsync.cpp \ 32 | test/rsynctest.cpp \ 33 | test/oobServer.cpp 34 | 35 | HEADERS += \ 36 | socket.h \ 37 | common.h \ 38 | sysutil.h \ 39 | test/echo.h \ 40 | syncserver.h \ 41 | protobuf/filesync.pb.h \ 42 | codec.h \ 43 | parseconfig.h \ 44 | str_tool.h \ 45 | rsync.h 46 | 47 | DISTFILES += \ 48 | protobuf/filesync.proto 49 | -------------------------------------------------------------------------------- /filesync.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {3c5f4f3c-2017-4a62-9586-112a4c06d772} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | 60 | 61 | 62 | ProjectExplorer.Project.Target.0 63 | 64 | Desktop Qt 5.6.1 GCC 64bit 65 | Desktop Qt 5.6.1 GCC 64bit 66 | qt.56.gcc_64_kit 67 | 0 68 | 0 69 | 0 70 | 71 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug 72 | 73 | 74 | true 75 | qmake 76 | 77 | QtProjectManager.QMakeBuildStep 78 | true 79 | 80 | false 81 | false 82 | false 83 | 84 | 85 | true 86 | Make 87 | 88 | Qt4ProjectManager.MakeStep 89 | 90 | -w 91 | -r 92 | 93 | false 94 | 95 | 96 | 97 | 2 98 | 构建 99 | 100 | ProjectExplorer.BuildSteps.Build 101 | 102 | 103 | 104 | true 105 | Make 106 | 107 | Qt4ProjectManager.MakeStep 108 | 109 | -w 110 | -r 111 | 112 | true 113 | clean 114 | 115 | 116 | 1 117 | 清理 118 | 119 | ProjectExplorer.BuildSteps.Clean 120 | 121 | 2 122 | false 123 | 124 | Debug 125 | 126 | Qt4ProjectManager.Qt4BuildConfiguration 127 | 2 128 | true 129 | 130 | 131 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Release 132 | 133 | 134 | true 135 | qmake 136 | 137 | QtProjectManager.QMakeBuildStep 138 | false 139 | 140 | false 141 | false 142 | false 143 | 144 | 145 | true 146 | Make 147 | 148 | Qt4ProjectManager.MakeStep 149 | 150 | -w 151 | -r 152 | 153 | false 154 | 155 | 156 | 157 | 2 158 | 构建 159 | 160 | ProjectExplorer.BuildSteps.Build 161 | 162 | 163 | 164 | true 165 | Make 166 | 167 | Qt4ProjectManager.MakeStep 168 | 169 | -w 170 | -r 171 | 172 | true 173 | clean 174 | 175 | 176 | 1 177 | 清理 178 | 179 | ProjectExplorer.BuildSteps.Clean 180 | 181 | 2 182 | false 183 | 184 | Release 185 | 186 | Qt4ProjectManager.Qt4BuildConfiguration 187 | 0 188 | true 189 | 190 | 191 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Profile 192 | 193 | 194 | true 195 | qmake 196 | 197 | QtProjectManager.QMakeBuildStep 198 | true 199 | 200 | false 201 | true 202 | false 203 | 204 | 205 | true 206 | Make 207 | 208 | Qt4ProjectManager.MakeStep 209 | 210 | -w 211 | -r 212 | 213 | false 214 | 215 | 216 | 217 | 2 218 | 构建 219 | 220 | ProjectExplorer.BuildSteps.Build 221 | 222 | 223 | 224 | true 225 | Make 226 | 227 | Qt4ProjectManager.MakeStep 228 | 229 | -w 230 | -r 231 | 232 | true 233 | clean 234 | 235 | 236 | 1 237 | 清理 238 | 239 | ProjectExplorer.BuildSteps.Clean 240 | 241 | 2 242 | false 243 | 244 | Profile 245 | 246 | Qt4ProjectManager.Qt4BuildConfiguration 247 | 0 248 | true 249 | 250 | 3 251 | 252 | 253 | 0 254 | 部署 255 | 256 | ProjectExplorer.BuildSteps.Deploy 257 | 258 | 1 259 | Deploy locally 260 | 261 | ProjectExplorer.DefaultDeployConfiguration 262 | 263 | 1 264 | 265 | 266 | false 267 | false 268 | 1000 269 | 270 | true 271 | 272 | false 273 | false 274 | false 275 | false 276 | true 277 | 0.01 278 | 10 279 | true 280 | 1 281 | 25 282 | 283 | 1 284 | true 285 | false 286 | true 287 | valgrind 288 | 289 | 0 290 | 1 291 | 2 292 | 3 293 | 4 294 | 5 295 | 6 296 | 7 297 | 8 298 | 9 299 | 10 300 | 11 301 | 12 302 | 13 303 | 14 304 | 305 | 2 306 | 307 | filesync 308 | 309 | Qt4ProjectManager.Qt4RunConfiguration:/home/chen/filesync/filesync.pro 310 | true 311 | 312 | filesync.pro 313 | false 314 | 315 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug 316 | 3768 317 | false 318 | true 319 | false 320 | false 321 | true 322 | 323 | 324 | false 325 | false 326 | 1000 327 | 328 | true 329 | 330 | false 331 | false 332 | false 333 | false 334 | true 335 | 0.01 336 | 10 337 | true 338 | 1 339 | 25 340 | 341 | 1 342 | true 343 | false 344 | true 345 | valgrind 346 | 347 | 0 348 | 1 349 | 2 350 | 3 351 | 4 352 | 5 353 | 6 354 | 7 355 | 8 356 | 9 357 | 10 358 | 11 359 | 12 360 | 13 361 | 14 362 | 363 | 2 364 | 365 | 366 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug/filesync 367 | true 368 | %{buildDir} 369 | 运行/home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug/filesync 370 | 自定义执行档 371 | ProjectExplorer.CustomExecutableRunConfiguration 372 | 3768 373 | false 374 | true 375 | false 376 | false 377 | true 378 | 379 | 2 380 | 381 | 382 | 383 | ProjectExplorer.Project.TargetCount 384 | 1 385 | 386 | 387 | ProjectExplorer.Project.Updater.FileVersion 388 | 18 389 | 390 | 391 | Version 392 | 18 393 | 394 | 395 | -------------------------------------------------------------------------------- /filesync.pro.user.3c5f4f3: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {3c5f4f3c-2017-4a62-9586-112a4c06d772} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | 60 | 61 | 62 | ProjectExplorer.Project.Target.0 63 | 64 | Desktop Qt 5.6.1 GCC 64bit 65 | Desktop Qt 5.6.1 GCC 64bit 66 | qt.56.gcc_64_kit 67 | 0 68 | 0 69 | 0 70 | 71 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug 72 | 73 | 74 | true 75 | qmake 76 | 77 | QtProjectManager.QMakeBuildStep 78 | true 79 | 80 | false 81 | false 82 | false 83 | 84 | 85 | true 86 | Make 87 | 88 | Qt4ProjectManager.MakeStep 89 | 90 | -w 91 | -r 92 | 93 | false 94 | 95 | 96 | 97 | 2 98 | 构建 99 | 100 | ProjectExplorer.BuildSteps.Build 101 | 102 | 103 | 104 | true 105 | Make 106 | 107 | Qt4ProjectManager.MakeStep 108 | 109 | -w 110 | -r 111 | 112 | true 113 | clean 114 | 115 | 116 | 1 117 | 清理 118 | 119 | ProjectExplorer.BuildSteps.Clean 120 | 121 | 2 122 | false 123 | 124 | Debug 125 | 126 | Qt4ProjectManager.Qt4BuildConfiguration 127 | 2 128 | true 129 | 130 | 131 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Release 132 | 133 | 134 | true 135 | qmake 136 | 137 | QtProjectManager.QMakeBuildStep 138 | false 139 | 140 | false 141 | false 142 | false 143 | 144 | 145 | true 146 | Make 147 | 148 | Qt4ProjectManager.MakeStep 149 | 150 | -w 151 | -r 152 | 153 | false 154 | 155 | 156 | 157 | 2 158 | 构建 159 | 160 | ProjectExplorer.BuildSteps.Build 161 | 162 | 163 | 164 | true 165 | Make 166 | 167 | Qt4ProjectManager.MakeStep 168 | 169 | -w 170 | -r 171 | 172 | true 173 | clean 174 | 175 | 176 | 1 177 | 清理 178 | 179 | ProjectExplorer.BuildSteps.Clean 180 | 181 | 2 182 | false 183 | 184 | Release 185 | 186 | Qt4ProjectManager.Qt4BuildConfiguration 187 | 0 188 | true 189 | 190 | 191 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Profile 192 | 193 | 194 | true 195 | qmake 196 | 197 | QtProjectManager.QMakeBuildStep 198 | true 199 | 200 | false 201 | true 202 | false 203 | 204 | 205 | true 206 | Make 207 | 208 | Qt4ProjectManager.MakeStep 209 | 210 | -w 211 | -r 212 | 213 | false 214 | 215 | 216 | 217 | 2 218 | 构建 219 | 220 | ProjectExplorer.BuildSteps.Build 221 | 222 | 223 | 224 | true 225 | Make 226 | 227 | Qt4ProjectManager.MakeStep 228 | 229 | -w 230 | -r 231 | 232 | true 233 | clean 234 | 235 | 236 | 1 237 | 清理 238 | 239 | ProjectExplorer.BuildSteps.Clean 240 | 241 | 2 242 | false 243 | 244 | Profile 245 | 246 | Qt4ProjectManager.Qt4BuildConfiguration 247 | 0 248 | true 249 | 250 | 3 251 | 252 | 253 | 0 254 | 部署 255 | 256 | ProjectExplorer.BuildSteps.Deploy 257 | 258 | 1 259 | Deploy locally 260 | 261 | ProjectExplorer.DefaultDeployConfiguration 262 | 263 | 1 264 | 265 | 266 | false 267 | false 268 | 1000 269 | 270 | true 271 | 272 | false 273 | false 274 | false 275 | false 276 | true 277 | 0.01 278 | 10 279 | true 280 | 1 281 | 25 282 | 283 | 1 284 | true 285 | false 286 | true 287 | valgrind 288 | 289 | 0 290 | 1 291 | 2 292 | 3 293 | 4 294 | 5 295 | 6 296 | 7 297 | 8 298 | 9 299 | 10 300 | 11 301 | 12 302 | 13 303 | 14 304 | 305 | 2 306 | 307 | filesync 308 | 309 | Qt4ProjectManager.Qt4RunConfiguration:/home/chen/filesync/filesync.pro 310 | true 311 | 312 | filesync.pro 313 | false 314 | 315 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug 316 | 3768 317 | false 318 | true 319 | false 320 | false 321 | true 322 | 323 | 324 | false 325 | false 326 | 1000 327 | 328 | true 329 | 330 | false 331 | false 332 | false 333 | false 334 | true 335 | 0.01 336 | 10 337 | true 338 | 1 339 | 25 340 | 341 | 1 342 | true 343 | false 344 | true 345 | valgrind 346 | 347 | 0 348 | 1 349 | 2 350 | 3 351 | 4 352 | 5 353 | 6 354 | 7 355 | 8 356 | 9 357 | 10 358 | 11 359 | 12 360 | 13 361 | 14 362 | 363 | 2 364 | 365 | 366 | /home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug/filesync 367 | true 368 | %{buildDir} 369 | 运行/home/chen/build-filesync-Desktop_Qt_5_6_1_GCC_64bit-Debug/filesync 370 | 自定义执行档 371 | ProjectExplorer.CustomExecutableRunConfiguration 372 | 3768 373 | false 374 | true 375 | false 376 | false 377 | true 378 | 379 | 2 380 | 381 | 382 | 383 | ProjectExplorer.Project.TargetCount 384 | 1 385 | 386 | 387 | ProjectExplorer.Project.Updater.FileVersion 388 | 18 389 | 390 | 391 | Version 392 | 18 393 | 394 | 395 | -------------------------------------------------------------------------------- /filesync.pro.user.dc6fb4f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehechen/filesync/735496ced476258eb5793fe58dc497f7395af543/filesync.pro.user.dc6fb4f -------------------------------------------------------------------------------- /hehe: -------------------------------------------------------------------------------- 1 | a;slkfdjalsnc;lsv;lajf;lwanf;lw;g 2 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | //#include "syncserver.h" 2 | 3 | //using namespace std; 4 | //int main() 5 | //{ 6 | // muduo::net::EventLoop loop; 7 | // SyncServer server(&loop,8888); //最后要有/ 8 | // server.start(); 9 | // loop.loop(); 10 | // return 0; 11 | //} 12 | -------------------------------------------------------------------------------- /md5.h: -------------------------------------------------------------------------------- 1 | #ifndef MD5_H 2 | #define MD5_H 3 | 4 | #include 5 | #include 6 | 7 | 8 | 9 | namespace md5 10 | { 11 | /* Type define */ 12 | typedef unsigned char byte; 13 | typedef unsigned int ulong; 14 | 15 | using std::string; 16 | using std::ifstream; 17 | 18 | /* MD5 declaration. */ 19 | class MD5 { 20 | public: 21 | MD5(); 22 | MD5(const void *input, size_t length); 23 | MD5(const string &str); 24 | MD5(ifstream &in); 25 | void update(const void *input, size_t length); 26 | void update(const string &str); 27 | void update(ifstream &in); 28 | const byte* digest(); 29 | string toString(); 30 | void reset(); 31 | private: 32 | void update(const byte *input, size_t length); 33 | void final(); 34 | void transform(const byte block[64]); 35 | void encode(const ulong *input, byte *output, size_t length); 36 | void decode(const byte *input, ulong *output, size_t length); 37 | string bytesToHexString(const byte *input, size_t length); 38 | 39 | /* class uncopyable */ 40 | MD5(const MD5&); 41 | MD5& operator=(const MD5&); 42 | private: 43 | ulong _state[4]; /* state (ABCD) */ 44 | ulong _count[2]; /* number of bits, modulo 2^64 (low-order word first) */ 45 | byte _buffer[64]; /* input buffer */ 46 | byte _digest[16]; /* message digest */ 47 | bool _finished; /* calculate finished ? */ 48 | 49 | static const byte PADDING[64]; /* padding for calculate */ 50 | static const char HEX[16]; 51 | static const size_t BUFFER_SIZE = 1024; 52 | }; 53 | } 54 | 55 | #endif/*MD5_H*/ 56 | -------------------------------------------------------------------------------- /parseconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "parseconfig.h" 2 | #include "str_tool.h" 3 | //在进入主函数前就初始化,保证线程安全 4 | ParseConfig *ParseConfig::m_instance = new ParseConfig(); 5 | ParseConfig *ParseConfig::getInstance() 6 | { 7 | return m_instance; 8 | } 9 | 10 | ParseConfig::ParseConfig():CONFILE("syncserver.conf") 11 | { 12 | atexit(destroy); //在程序退出时销毁 13 | } 14 | ParseConfig::~ParseConfig() 15 | { 16 | } 17 | 18 | void ParseConfig::destroy() 19 | { 20 | if(m_instance) 21 | { 22 | delete m_instance; 23 | m_instance = nullptr; 24 | CHEN_LOG(DEBUG,"ParseConfig destroy"); 25 | } 26 | } 27 | /** 28 | * 加载配置文件 29 | */ 30 | void ParseConfig::loadfile() 31 | { 32 | FILE* fp = fopen(CONFILE,"r"); //只读模式打开配置文件 33 | if(fp == NULL) 34 | CHEN_LOG(ERROR,"open confile error"); 35 | 36 | int linenumber = 0;//这个参数用于记录配置文件的行数,便于在配置文件出错时打印提醒 37 | char* line;//行指针 38 | char key[128] = {0};//保存命令的key 39 | char value[128] = {0};//保存命令的value 40 | char linebuf[MAX_CONF_LEN+1];//保存读取到的行 41 | while(fgets(linebuf,sizeof(linebuf),fp)) 42 | { 43 | ++linenumber;//行数++ 44 | line = str_delspace(linebuf);//去除行首和行尾的空格、\r\n 45 | if (line[0] == '#' || line[0] == '\0') 46 | { 47 | continue;//注释或空行直接跳过 48 | } 49 | str_split(line,key,value,'=');//根据等号切割 50 | strcpy(key,str_delspace(key));//去除空格 51 | strcpy(value,str_delspace(value));//去除空格 52 | if(0 == strlen(value)) 53 | {//某些key没有配置value,提示key和行号 54 | CHEN_LOG(WARN,"missing value in %s for %s locate line %d",CONFILE,key,linenumber); 55 | } 56 | //strcasecmp忽略大小写比较字符串 57 | if(strcasecmp(key, "syncroot") == 0)//服务端同步路径 58 | { 59 | syncRoot = value; 60 | CHEN_LOG(DEBUG,"SYNCROOT:%s",value); 61 | } 62 | else 63 | {//用户名和密码 64 | userInfos[string(key)] = std::move(string(value)); 65 | CHEN_LOG(DEBUG,"user:%s,pw:%s",key,value); 66 | } 67 | } 68 | //关闭配置文件 69 | fclose(fp); 70 | } 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /parseconfig.h: -------------------------------------------------------------------------------- 1 | //解析配置文件的类 2 | #ifndef _PARSECONFIH_H 3 | #define _PARSECONFIH_H 4 | 5 | #include "common.h" 6 | #include 7 | #include 8 | //饿汉模式单例类 9 | class ParseConfig 10 | { 11 | public: 12 | //返回单例对象 13 | static ParseConfig *getInstance(); 14 | void loadfile(); //加载配置文件 15 | //获取配置数据 16 | std::string getSyncRoot() {return syncRoot;} 17 | //检查用户名和密码是否正确 18 | bool checkUser(std::string &username,std::string &pw) 19 | { 20 | auto it = userInfos.find(username); 21 | if(it != userInfos.end()) 22 | { 23 | if(it->second == pw) 24 | return true; 25 | } 26 | return false; 27 | } 28 | 29 | private: 30 | static ParseConfig *m_instance; 31 | static void destroy(); //销毁该单例 32 | const char* CONFILE;//配置文件的文件名 33 | static const int MAX_CONF_LEN = 1024; 34 | ParseConfig(); 35 | ~ParseConfig(); 36 | 37 | std::string syncRoot; //服务端的同步目录 38 | std::unordered_map userInfos; //用户名和密码 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /protobuf/compile_proto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | protoc -I=./ --cpp_out=./ *.proto 4 | -------------------------------------------------------------------------------- /protobuf/filesync.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: filesync.proto 3 | 4 | #ifndef PROTOBUF_filesync_2eproto__INCLUDED 5 | #define PROTOBUF_filesync_2eproto__INCLUDED 6 | 7 | #include 8 | 9 | #include 10 | 11 | #if GOOGLE_PROTOBUF_VERSION < 3000000 12 | #error This file was generated by a newer version of protoc which is 13 | #error incompatible with your Protocol Buffer headers. Please update 14 | #error your headers. 15 | #endif 16 | #if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 17 | #error This file was generated by an older version of protoc which is 18 | #error incompatible with your Protocol Buffer headers. Please 19 | #error regenerate this file with a newer version of protoc. 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | // @@protoc_insertion_point(includes) 31 | 32 | namespace filesync { 33 | 34 | // Internal implementation detail -- do not call these. 35 | void protobuf_AddDesc_filesync_2eproto(); 36 | void protobuf_AssignDesc_filesync_2eproto(); 37 | void protobuf_ShutdownFile_filesync_2eproto(); 38 | 39 | class FileInfo; 40 | class Init; 41 | class IsControl; 42 | class SendFile; 43 | class SignIn; 44 | class SyncInfo; 45 | 46 | // =================================================================== 47 | 48 | class SyncInfo : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:filesync.SyncInfo) */ { 49 | public: 50 | SyncInfo(); 51 | virtual ~SyncInfo(); 52 | 53 | SyncInfo(const SyncInfo& from); 54 | 55 | inline SyncInfo& operator=(const SyncInfo& from) { 56 | CopyFrom(from); 57 | return *this; 58 | } 59 | 60 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 61 | return _internal_metadata_.unknown_fields(); 62 | } 63 | 64 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 65 | return _internal_metadata_.mutable_unknown_fields(); 66 | } 67 | 68 | static const ::google::protobuf::Descriptor* descriptor(); 69 | static const SyncInfo& default_instance(); 70 | 71 | void Swap(SyncInfo* other); 72 | 73 | // implements Message ---------------------------------------------- 74 | 75 | inline SyncInfo* New() const { return New(NULL); } 76 | 77 | SyncInfo* New(::google::protobuf::Arena* arena) const; 78 | void CopyFrom(const ::google::protobuf::Message& from); 79 | void MergeFrom(const ::google::protobuf::Message& from); 80 | void CopyFrom(const SyncInfo& from); 81 | void MergeFrom(const SyncInfo& from); 82 | void Clear(); 83 | bool IsInitialized() const; 84 | 85 | int ByteSize() const; 86 | bool MergePartialFromCodedStream( 87 | ::google::protobuf::io::CodedInputStream* input); 88 | void SerializeWithCachedSizes( 89 | ::google::protobuf::io::CodedOutputStream* output) const; 90 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 91 | bool deterministic, ::google::protobuf::uint8* output) const; 92 | ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { 93 | return InternalSerializeWithCachedSizesToArray(false, output); 94 | } 95 | int GetCachedSize() const { return _cached_size_; } 96 | private: 97 | void SharedCtor(); 98 | void SharedDtor(); 99 | void SetCachedSize(int size) const; 100 | void InternalSwap(SyncInfo* other); 101 | private: 102 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 103 | return _internal_metadata_.arena(); 104 | } 105 | inline void* MaybeArenaPtr() const { 106 | return _internal_metadata_.raw_arena_ptr(); 107 | } 108 | public: 109 | 110 | ::google::protobuf::Metadata GetMetadata() const; 111 | 112 | // nested types ---------------------------------------------------- 113 | 114 | // accessors ------------------------------------------------------- 115 | 116 | // required int32 id = 1; 117 | bool has_id() const; 118 | void clear_id(); 119 | static const int kIdFieldNumber = 1; 120 | ::google::protobuf::int32 id() const; 121 | void set_id(::google::protobuf::int32 value); 122 | 123 | // required string filename = 2; 124 | bool has_filename() const; 125 | void clear_filename(); 126 | static const int kFilenameFieldNumber = 2; 127 | const ::std::string& filename() const; 128 | void set_filename(const ::std::string& value); 129 | void set_filename(const char* value); 130 | void set_filename(const char* value, size_t size); 131 | ::std::string* mutable_filename(); 132 | ::std::string* release_filename(); 133 | void set_allocated_filename(::std::string* filename); 134 | 135 | // optional string newFilename = 3; 136 | bool has_newfilename() const; 137 | void clear_newfilename(); 138 | static const int kNewFilenameFieldNumber = 3; 139 | const ::std::string& newfilename() const; 140 | void set_newfilename(const ::std::string& value); 141 | void set_newfilename(const char* value); 142 | void set_newfilename(const char* value, size_t size); 143 | ::std::string* mutable_newfilename(); 144 | ::std::string* release_newfilename(); 145 | void set_allocated_newfilename(::std::string* newfilename); 146 | 147 | // optional int32 size = 4; 148 | bool has_size() const; 149 | void clear_size(); 150 | static const int kSizeFieldNumber = 4; 151 | ::google::protobuf::int32 size() const; 152 | void set_size(::google::protobuf::int32 value); 153 | 154 | // optional string MD5 = 5; 155 | bool has_md5() const; 156 | void clear_md5(); 157 | static const int kMD5FieldNumber = 5; 158 | const ::std::string& md5() const; 159 | void set_md5(const ::std::string& value); 160 | void set_md5(const char* value); 161 | void set_md5(const char* value, size_t size); 162 | ::std::string* mutable_md5(); 163 | ::std::string* release_md5(); 164 | void set_allocated_md5(::std::string* md5); 165 | 166 | // @@protoc_insertion_point(class_scope:filesync.SyncInfo) 167 | private: 168 | inline void set_has_id(); 169 | inline void clear_has_id(); 170 | inline void set_has_filename(); 171 | inline void clear_has_filename(); 172 | inline void set_has_newfilename(); 173 | inline void clear_has_newfilename(); 174 | inline void set_has_size(); 175 | inline void clear_has_size(); 176 | inline void set_has_md5(); 177 | inline void clear_has_md5(); 178 | 179 | // helper for ByteSize() 180 | int RequiredFieldsByteSizeFallback() const; 181 | 182 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 183 | ::google::protobuf::uint32 _has_bits_[1]; 184 | mutable int _cached_size_; 185 | ::google::protobuf::internal::ArenaStringPtr filename_; 186 | ::google::protobuf::int32 id_; 187 | ::google::protobuf::int32 size_; 188 | ::google::protobuf::internal::ArenaStringPtr newfilename_; 189 | ::google::protobuf::internal::ArenaStringPtr md5_; 190 | friend void protobuf_AddDesc_filesync_2eproto(); 191 | friend void protobuf_AssignDesc_filesync_2eproto(); 192 | friend void protobuf_ShutdownFile_filesync_2eproto(); 193 | 194 | void InitAsDefaultInstance(); 195 | static SyncInfo* default_instance_; 196 | }; 197 | // ------------------------------------------------------------------- 198 | 199 | class SignIn : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:filesync.SignIn) */ { 200 | public: 201 | SignIn(); 202 | virtual ~SignIn(); 203 | 204 | SignIn(const SignIn& from); 205 | 206 | inline SignIn& operator=(const SignIn& from) { 207 | CopyFrom(from); 208 | return *this; 209 | } 210 | 211 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 212 | return _internal_metadata_.unknown_fields(); 213 | } 214 | 215 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 216 | return _internal_metadata_.mutable_unknown_fields(); 217 | } 218 | 219 | static const ::google::protobuf::Descriptor* descriptor(); 220 | static const SignIn& default_instance(); 221 | 222 | void Swap(SignIn* other); 223 | 224 | // implements Message ---------------------------------------------- 225 | 226 | inline SignIn* New() const { return New(NULL); } 227 | 228 | SignIn* New(::google::protobuf::Arena* arena) const; 229 | void CopyFrom(const ::google::protobuf::Message& from); 230 | void MergeFrom(const ::google::protobuf::Message& from); 231 | void CopyFrom(const SignIn& from); 232 | void MergeFrom(const SignIn& from); 233 | void Clear(); 234 | bool IsInitialized() const; 235 | 236 | int ByteSize() const; 237 | bool MergePartialFromCodedStream( 238 | ::google::protobuf::io::CodedInputStream* input); 239 | void SerializeWithCachedSizes( 240 | ::google::protobuf::io::CodedOutputStream* output) const; 241 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 242 | bool deterministic, ::google::protobuf::uint8* output) const; 243 | ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { 244 | return InternalSerializeWithCachedSizesToArray(false, output); 245 | } 246 | int GetCachedSize() const { return _cached_size_; } 247 | private: 248 | void SharedCtor(); 249 | void SharedDtor(); 250 | void SetCachedSize(int size) const; 251 | void InternalSwap(SignIn* other); 252 | private: 253 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 254 | return _internal_metadata_.arena(); 255 | } 256 | inline void* MaybeArenaPtr() const { 257 | return _internal_metadata_.raw_arena_ptr(); 258 | } 259 | public: 260 | 261 | ::google::protobuf::Metadata GetMetadata() const; 262 | 263 | // nested types ---------------------------------------------------- 264 | 265 | // accessors ------------------------------------------------------- 266 | 267 | // required string username = 1; 268 | bool has_username() const; 269 | void clear_username(); 270 | static const int kUsernameFieldNumber = 1; 271 | const ::std::string& username() const; 272 | void set_username(const ::std::string& value); 273 | void set_username(const char* value); 274 | void set_username(const char* value, size_t size); 275 | ::std::string* mutable_username(); 276 | ::std::string* release_username(); 277 | void set_allocated_username(::std::string* username); 278 | 279 | // required string password = 2; 280 | bool has_password() const; 281 | void clear_password(); 282 | static const int kPasswordFieldNumber = 2; 283 | const ::std::string& password() const; 284 | void set_password(const ::std::string& value); 285 | void set_password(const char* value); 286 | void set_password(const char* value, size_t size); 287 | ::std::string* mutable_password(); 288 | ::std::string* release_password(); 289 | void set_allocated_password(::std::string* password); 290 | 291 | // @@protoc_insertion_point(class_scope:filesync.SignIn) 292 | private: 293 | inline void set_has_username(); 294 | inline void clear_has_username(); 295 | inline void set_has_password(); 296 | inline void clear_has_password(); 297 | 298 | // helper for ByteSize() 299 | int RequiredFieldsByteSizeFallback() const; 300 | 301 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 302 | ::google::protobuf::uint32 _has_bits_[1]; 303 | mutable int _cached_size_; 304 | ::google::protobuf::internal::ArenaStringPtr username_; 305 | ::google::protobuf::internal::ArenaStringPtr password_; 306 | friend void protobuf_AddDesc_filesync_2eproto(); 307 | friend void protobuf_AssignDesc_filesync_2eproto(); 308 | friend void protobuf_ShutdownFile_filesync_2eproto(); 309 | 310 | void InitAsDefaultInstance(); 311 | static SignIn* default_instance_; 312 | }; 313 | // ------------------------------------------------------------------- 314 | 315 | class Init : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:filesync.Init) */ { 316 | public: 317 | Init(); 318 | virtual ~Init(); 319 | 320 | Init(const Init& from); 321 | 322 | inline Init& operator=(const Init& from) { 323 | CopyFrom(from); 324 | return *this; 325 | } 326 | 327 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 328 | return _internal_metadata_.unknown_fields(); 329 | } 330 | 331 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 332 | return _internal_metadata_.mutable_unknown_fields(); 333 | } 334 | 335 | static const ::google::protobuf::Descriptor* descriptor(); 336 | static const Init& default_instance(); 337 | 338 | void Swap(Init* other); 339 | 340 | // implements Message ---------------------------------------------- 341 | 342 | inline Init* New() const { return New(NULL); } 343 | 344 | Init* New(::google::protobuf::Arena* arena) const; 345 | void CopyFrom(const ::google::protobuf::Message& from); 346 | void MergeFrom(const ::google::protobuf::Message& from); 347 | void CopyFrom(const Init& from); 348 | void MergeFrom(const Init& from); 349 | void Clear(); 350 | bool IsInitialized() const; 351 | 352 | int ByteSize() const; 353 | bool MergePartialFromCodedStream( 354 | ::google::protobuf::io::CodedInputStream* input); 355 | void SerializeWithCachedSizes( 356 | ::google::protobuf::io::CodedOutputStream* output) const; 357 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 358 | bool deterministic, ::google::protobuf::uint8* output) const; 359 | ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { 360 | return InternalSerializeWithCachedSizesToArray(false, output); 361 | } 362 | int GetCachedSize() const { return _cached_size_; } 363 | private: 364 | void SharedCtor(); 365 | void SharedDtor(); 366 | void SetCachedSize(int size) const; 367 | void InternalSwap(Init* other); 368 | private: 369 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 370 | return _internal_metadata_.arena(); 371 | } 372 | inline void* MaybeArenaPtr() const { 373 | return _internal_metadata_.raw_arena_ptr(); 374 | } 375 | public: 376 | 377 | ::google::protobuf::Metadata GetMetadata() const; 378 | 379 | // nested types ---------------------------------------------------- 380 | 381 | // accessors ------------------------------------------------------- 382 | 383 | // repeated .filesync.SyncInfo info = 3; 384 | int info_size() const; 385 | void clear_info(); 386 | static const int kInfoFieldNumber = 3; 387 | const ::filesync::SyncInfo& info(int index) const; 388 | ::filesync::SyncInfo* mutable_info(int index); 389 | ::filesync::SyncInfo* add_info(); 390 | ::google::protobuf::RepeatedPtrField< ::filesync::SyncInfo >* 391 | mutable_info(); 392 | const ::google::protobuf::RepeatedPtrField< ::filesync::SyncInfo >& 393 | info() const; 394 | 395 | // @@protoc_insertion_point(class_scope:filesync.Init) 396 | private: 397 | 398 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 399 | ::google::protobuf::uint32 _has_bits_[1]; 400 | mutable int _cached_size_; 401 | ::google::protobuf::RepeatedPtrField< ::filesync::SyncInfo > info_; 402 | friend void protobuf_AddDesc_filesync_2eproto(); 403 | friend void protobuf_AssignDesc_filesync_2eproto(); 404 | friend void protobuf_ShutdownFile_filesync_2eproto(); 405 | 406 | void InitAsDefaultInstance(); 407 | static Init* default_instance_; 408 | }; 409 | // ------------------------------------------------------------------- 410 | 411 | class SendFile : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:filesync.SendFile) */ { 412 | public: 413 | SendFile(); 414 | virtual ~SendFile(); 415 | 416 | SendFile(const SendFile& from); 417 | 418 | inline SendFile& operator=(const SendFile& from) { 419 | CopyFrom(from); 420 | return *this; 421 | } 422 | 423 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 424 | return _internal_metadata_.unknown_fields(); 425 | } 426 | 427 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 428 | return _internal_metadata_.mutable_unknown_fields(); 429 | } 430 | 431 | static const ::google::protobuf::Descriptor* descriptor(); 432 | static const SendFile& default_instance(); 433 | 434 | void Swap(SendFile* other); 435 | 436 | // implements Message ---------------------------------------------- 437 | 438 | inline SendFile* New() const { return New(NULL); } 439 | 440 | SendFile* New(::google::protobuf::Arena* arena) const; 441 | void CopyFrom(const ::google::protobuf::Message& from); 442 | void MergeFrom(const ::google::protobuf::Message& from); 443 | void CopyFrom(const SendFile& from); 444 | void MergeFrom(const SendFile& from); 445 | void Clear(); 446 | bool IsInitialized() const; 447 | 448 | int ByteSize() const; 449 | bool MergePartialFromCodedStream( 450 | ::google::protobuf::io::CodedInputStream* input); 451 | void SerializeWithCachedSizes( 452 | ::google::protobuf::io::CodedOutputStream* output) const; 453 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 454 | bool deterministic, ::google::protobuf::uint8* output) const; 455 | ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { 456 | return InternalSerializeWithCachedSizesToArray(false, output); 457 | } 458 | int GetCachedSize() const { return _cached_size_; } 459 | private: 460 | void SharedCtor(); 461 | void SharedDtor(); 462 | void SetCachedSize(int size) const; 463 | void InternalSwap(SendFile* other); 464 | private: 465 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 466 | return _internal_metadata_.arena(); 467 | } 468 | inline void* MaybeArenaPtr() const { 469 | return _internal_metadata_.raw_arena_ptr(); 470 | } 471 | public: 472 | 473 | ::google::protobuf::Metadata GetMetadata() const; 474 | 475 | // nested types ---------------------------------------------------- 476 | 477 | // accessors ------------------------------------------------------- 478 | 479 | // required int32 id = 1; 480 | bool has_id() const; 481 | void clear_id(); 482 | static const int kIdFieldNumber = 1; 483 | ::google::protobuf::int32 id() const; 484 | void set_id(::google::protobuf::int32 value); 485 | 486 | // required string filename = 2; 487 | bool has_filename() const; 488 | void clear_filename(); 489 | static const int kFilenameFieldNumber = 2; 490 | const ::std::string& filename() const; 491 | void set_filename(const ::std::string& value); 492 | void set_filename(const char* value); 493 | void set_filename(const char* value, size_t size); 494 | ::std::string* mutable_filename(); 495 | ::std::string* release_filename(); 496 | void set_allocated_filename(::std::string* filename); 497 | 498 | // @@protoc_insertion_point(class_scope:filesync.SendFile) 499 | private: 500 | inline void set_has_id(); 501 | inline void clear_has_id(); 502 | inline void set_has_filename(); 503 | inline void clear_has_filename(); 504 | 505 | // helper for ByteSize() 506 | int RequiredFieldsByteSizeFallback() const; 507 | 508 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 509 | ::google::protobuf::uint32 _has_bits_[1]; 510 | mutable int _cached_size_; 511 | ::google::protobuf::internal::ArenaStringPtr filename_; 512 | ::google::protobuf::int32 id_; 513 | friend void protobuf_AddDesc_filesync_2eproto(); 514 | friend void protobuf_AssignDesc_filesync_2eproto(); 515 | friend void protobuf_ShutdownFile_filesync_2eproto(); 516 | 517 | void InitAsDefaultInstance(); 518 | static SendFile* default_instance_; 519 | }; 520 | // ------------------------------------------------------------------- 521 | 522 | class IsControl : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:filesync.IsControl) */ { 523 | public: 524 | IsControl(); 525 | virtual ~IsControl(); 526 | 527 | IsControl(const IsControl& from); 528 | 529 | inline IsControl& operator=(const IsControl& from) { 530 | CopyFrom(from); 531 | return *this; 532 | } 533 | 534 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 535 | return _internal_metadata_.unknown_fields(); 536 | } 537 | 538 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 539 | return _internal_metadata_.mutable_unknown_fields(); 540 | } 541 | 542 | static const ::google::protobuf::Descriptor* descriptor(); 543 | static const IsControl& default_instance(); 544 | 545 | void Swap(IsControl* other); 546 | 547 | // implements Message ---------------------------------------------- 548 | 549 | inline IsControl* New() const { return New(NULL); } 550 | 551 | IsControl* New(::google::protobuf::Arena* arena) const; 552 | void CopyFrom(const ::google::protobuf::Message& from); 553 | void MergeFrom(const ::google::protobuf::Message& from); 554 | void CopyFrom(const IsControl& from); 555 | void MergeFrom(const IsControl& from); 556 | void Clear(); 557 | bool IsInitialized() const; 558 | 559 | int ByteSize() const; 560 | bool MergePartialFromCodedStream( 561 | ::google::protobuf::io::CodedInputStream* input); 562 | void SerializeWithCachedSizes( 563 | ::google::protobuf::io::CodedOutputStream* output) const; 564 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 565 | bool deterministic, ::google::protobuf::uint8* output) const; 566 | ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { 567 | return InternalSerializeWithCachedSizesToArray(false, output); 568 | } 569 | int GetCachedSize() const { return _cached_size_; } 570 | private: 571 | void SharedCtor(); 572 | void SharedDtor(); 573 | void SetCachedSize(int size) const; 574 | void InternalSwap(IsControl* other); 575 | private: 576 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 577 | return _internal_metadata_.arena(); 578 | } 579 | inline void* MaybeArenaPtr() const { 580 | return _internal_metadata_.raw_arena_ptr(); 581 | } 582 | public: 583 | 584 | ::google::protobuf::Metadata GetMetadata() const; 585 | 586 | // nested types ---------------------------------------------------- 587 | 588 | // accessors ------------------------------------------------------- 589 | 590 | // required int32 id = 1; 591 | bool has_id() const; 592 | void clear_id(); 593 | static const int kIdFieldNumber = 1; 594 | ::google::protobuf::int32 id() const; 595 | void set_id(::google::protobuf::int32 value); 596 | 597 | // @@protoc_insertion_point(class_scope:filesync.IsControl) 598 | private: 599 | inline void set_has_id(); 600 | inline void clear_has_id(); 601 | 602 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 603 | ::google::protobuf::uint32 _has_bits_[1]; 604 | mutable int _cached_size_; 605 | ::google::protobuf::int32 id_; 606 | friend void protobuf_AddDesc_filesync_2eproto(); 607 | friend void protobuf_AssignDesc_filesync_2eproto(); 608 | friend void protobuf_ShutdownFile_filesync_2eproto(); 609 | 610 | void InitAsDefaultInstance(); 611 | static IsControl* default_instance_; 612 | }; 613 | // ------------------------------------------------------------------- 614 | 615 | class FileInfo : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:filesync.FileInfo) */ { 616 | public: 617 | FileInfo(); 618 | virtual ~FileInfo(); 619 | 620 | FileInfo(const FileInfo& from); 621 | 622 | inline FileInfo& operator=(const FileInfo& from) { 623 | CopyFrom(from); 624 | return *this; 625 | } 626 | 627 | inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 628 | return _internal_metadata_.unknown_fields(); 629 | } 630 | 631 | inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 632 | return _internal_metadata_.mutable_unknown_fields(); 633 | } 634 | 635 | static const ::google::protobuf::Descriptor* descriptor(); 636 | static const FileInfo& default_instance(); 637 | 638 | void Swap(FileInfo* other); 639 | 640 | // implements Message ---------------------------------------------- 641 | 642 | inline FileInfo* New() const { return New(NULL); } 643 | 644 | FileInfo* New(::google::protobuf::Arena* arena) const; 645 | void CopyFrom(const ::google::protobuf::Message& from); 646 | void MergeFrom(const ::google::protobuf::Message& from); 647 | void CopyFrom(const FileInfo& from); 648 | void MergeFrom(const FileInfo& from); 649 | void Clear(); 650 | bool IsInitialized() const; 651 | 652 | int ByteSize() const; 653 | bool MergePartialFromCodedStream( 654 | ::google::protobuf::io::CodedInputStream* input); 655 | void SerializeWithCachedSizes( 656 | ::google::protobuf::io::CodedOutputStream* output) const; 657 | ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( 658 | bool deterministic, ::google::protobuf::uint8* output) const; 659 | ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { 660 | return InternalSerializeWithCachedSizesToArray(false, output); 661 | } 662 | int GetCachedSize() const { return _cached_size_; } 663 | private: 664 | void SharedCtor(); 665 | void SharedDtor(); 666 | void SetCachedSize(int size) const; 667 | void InternalSwap(FileInfo* other); 668 | private: 669 | inline ::google::protobuf::Arena* GetArenaNoVirtual() const { 670 | return _internal_metadata_.arena(); 671 | } 672 | inline void* MaybeArenaPtr() const { 673 | return _internal_metadata_.raw_arena_ptr(); 674 | } 675 | public: 676 | 677 | ::google::protobuf::Metadata GetMetadata() const; 678 | 679 | // nested types ---------------------------------------------------- 680 | 681 | // accessors ------------------------------------------------------- 682 | 683 | // required int32 size = 1; 684 | bool has_size() const; 685 | void clear_size(); 686 | static const int kSizeFieldNumber = 1; 687 | ::google::protobuf::int32 size() const; 688 | void set_size(::google::protobuf::int32 value); 689 | 690 | // required string filename = 2; 691 | bool has_filename() const; 692 | void clear_filename(); 693 | static const int kFilenameFieldNumber = 2; 694 | const ::std::string& filename() const; 695 | void set_filename(const ::std::string& value); 696 | void set_filename(const char* value); 697 | void set_filename(const char* value, size_t size); 698 | ::std::string* mutable_filename(); 699 | ::std::string* release_filename(); 700 | void set_allocated_filename(::std::string* filename); 701 | 702 | // @@protoc_insertion_point(class_scope:filesync.FileInfo) 703 | private: 704 | inline void set_has_size(); 705 | inline void clear_has_size(); 706 | inline void set_has_filename(); 707 | inline void clear_has_filename(); 708 | 709 | // helper for ByteSize() 710 | int RequiredFieldsByteSizeFallback() const; 711 | 712 | ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; 713 | ::google::protobuf::uint32 _has_bits_[1]; 714 | mutable int _cached_size_; 715 | ::google::protobuf::internal::ArenaStringPtr filename_; 716 | ::google::protobuf::int32 size_; 717 | friend void protobuf_AddDesc_filesync_2eproto(); 718 | friend void protobuf_AssignDesc_filesync_2eproto(); 719 | friend void protobuf_ShutdownFile_filesync_2eproto(); 720 | 721 | void InitAsDefaultInstance(); 722 | static FileInfo* default_instance_; 723 | }; 724 | // =================================================================== 725 | 726 | 727 | // =================================================================== 728 | 729 | #if !PROTOBUF_INLINE_NOT_IN_HEADERS 730 | // SyncInfo 731 | 732 | // required int32 id = 1; 733 | inline bool SyncInfo::has_id() const { 734 | return (_has_bits_[0] & 0x00000001u) != 0; 735 | } 736 | inline void SyncInfo::set_has_id() { 737 | _has_bits_[0] |= 0x00000001u; 738 | } 739 | inline void SyncInfo::clear_has_id() { 740 | _has_bits_[0] &= ~0x00000001u; 741 | } 742 | inline void SyncInfo::clear_id() { 743 | id_ = 0; 744 | clear_has_id(); 745 | } 746 | inline ::google::protobuf::int32 SyncInfo::id() const { 747 | // @@protoc_insertion_point(field_get:filesync.SyncInfo.id) 748 | return id_; 749 | } 750 | inline void SyncInfo::set_id(::google::protobuf::int32 value) { 751 | set_has_id(); 752 | id_ = value; 753 | // @@protoc_insertion_point(field_set:filesync.SyncInfo.id) 754 | } 755 | 756 | // required string filename = 2; 757 | inline bool SyncInfo::has_filename() const { 758 | return (_has_bits_[0] & 0x00000002u) != 0; 759 | } 760 | inline void SyncInfo::set_has_filename() { 761 | _has_bits_[0] |= 0x00000002u; 762 | } 763 | inline void SyncInfo::clear_has_filename() { 764 | _has_bits_[0] &= ~0x00000002u; 765 | } 766 | inline void SyncInfo::clear_filename() { 767 | filename_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 768 | clear_has_filename(); 769 | } 770 | inline const ::std::string& SyncInfo::filename() const { 771 | // @@protoc_insertion_point(field_get:filesync.SyncInfo.filename) 772 | return filename_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 773 | } 774 | inline void SyncInfo::set_filename(const ::std::string& value) { 775 | set_has_filename(); 776 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 777 | // @@protoc_insertion_point(field_set:filesync.SyncInfo.filename) 778 | } 779 | inline void SyncInfo::set_filename(const char* value) { 780 | set_has_filename(); 781 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 782 | // @@protoc_insertion_point(field_set_char:filesync.SyncInfo.filename) 783 | } 784 | inline void SyncInfo::set_filename(const char* value, size_t size) { 785 | set_has_filename(); 786 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 787 | ::std::string(reinterpret_cast(value), size)); 788 | // @@protoc_insertion_point(field_set_pointer:filesync.SyncInfo.filename) 789 | } 790 | inline ::std::string* SyncInfo::mutable_filename() { 791 | set_has_filename(); 792 | // @@protoc_insertion_point(field_mutable:filesync.SyncInfo.filename) 793 | return filename_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 794 | } 795 | inline ::std::string* SyncInfo::release_filename() { 796 | // @@protoc_insertion_point(field_release:filesync.SyncInfo.filename) 797 | clear_has_filename(); 798 | return filename_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 799 | } 800 | inline void SyncInfo::set_allocated_filename(::std::string* filename) { 801 | if (filename != NULL) { 802 | set_has_filename(); 803 | } else { 804 | clear_has_filename(); 805 | } 806 | filename_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), filename); 807 | // @@protoc_insertion_point(field_set_allocated:filesync.SyncInfo.filename) 808 | } 809 | 810 | // optional string newFilename = 3; 811 | inline bool SyncInfo::has_newfilename() const { 812 | return (_has_bits_[0] & 0x00000004u) != 0; 813 | } 814 | inline void SyncInfo::set_has_newfilename() { 815 | _has_bits_[0] |= 0x00000004u; 816 | } 817 | inline void SyncInfo::clear_has_newfilename() { 818 | _has_bits_[0] &= ~0x00000004u; 819 | } 820 | inline void SyncInfo::clear_newfilename() { 821 | newfilename_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 822 | clear_has_newfilename(); 823 | } 824 | inline const ::std::string& SyncInfo::newfilename() const { 825 | // @@protoc_insertion_point(field_get:filesync.SyncInfo.newFilename) 826 | return newfilename_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 827 | } 828 | inline void SyncInfo::set_newfilename(const ::std::string& value) { 829 | set_has_newfilename(); 830 | newfilename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 831 | // @@protoc_insertion_point(field_set:filesync.SyncInfo.newFilename) 832 | } 833 | inline void SyncInfo::set_newfilename(const char* value) { 834 | set_has_newfilename(); 835 | newfilename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 836 | // @@protoc_insertion_point(field_set_char:filesync.SyncInfo.newFilename) 837 | } 838 | inline void SyncInfo::set_newfilename(const char* value, size_t size) { 839 | set_has_newfilename(); 840 | newfilename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 841 | ::std::string(reinterpret_cast(value), size)); 842 | // @@protoc_insertion_point(field_set_pointer:filesync.SyncInfo.newFilename) 843 | } 844 | inline ::std::string* SyncInfo::mutable_newfilename() { 845 | set_has_newfilename(); 846 | // @@protoc_insertion_point(field_mutable:filesync.SyncInfo.newFilename) 847 | return newfilename_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 848 | } 849 | inline ::std::string* SyncInfo::release_newfilename() { 850 | // @@protoc_insertion_point(field_release:filesync.SyncInfo.newFilename) 851 | clear_has_newfilename(); 852 | return newfilename_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 853 | } 854 | inline void SyncInfo::set_allocated_newfilename(::std::string* newfilename) { 855 | if (newfilename != NULL) { 856 | set_has_newfilename(); 857 | } else { 858 | clear_has_newfilename(); 859 | } 860 | newfilename_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), newfilename); 861 | // @@protoc_insertion_point(field_set_allocated:filesync.SyncInfo.newFilename) 862 | } 863 | 864 | // optional int32 size = 4; 865 | inline bool SyncInfo::has_size() const { 866 | return (_has_bits_[0] & 0x00000008u) != 0; 867 | } 868 | inline void SyncInfo::set_has_size() { 869 | _has_bits_[0] |= 0x00000008u; 870 | } 871 | inline void SyncInfo::clear_has_size() { 872 | _has_bits_[0] &= ~0x00000008u; 873 | } 874 | inline void SyncInfo::clear_size() { 875 | size_ = 0; 876 | clear_has_size(); 877 | } 878 | inline ::google::protobuf::int32 SyncInfo::size() const { 879 | // @@protoc_insertion_point(field_get:filesync.SyncInfo.size) 880 | return size_; 881 | } 882 | inline void SyncInfo::set_size(::google::protobuf::int32 value) { 883 | set_has_size(); 884 | size_ = value; 885 | // @@protoc_insertion_point(field_set:filesync.SyncInfo.size) 886 | } 887 | 888 | // optional string MD5 = 5; 889 | inline bool SyncInfo::has_md5() const { 890 | return (_has_bits_[0] & 0x00000010u) != 0; 891 | } 892 | inline void SyncInfo::set_has_md5() { 893 | _has_bits_[0] |= 0x00000010u; 894 | } 895 | inline void SyncInfo::clear_has_md5() { 896 | _has_bits_[0] &= ~0x00000010u; 897 | } 898 | inline void SyncInfo::clear_md5() { 899 | md5_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 900 | clear_has_md5(); 901 | } 902 | inline const ::std::string& SyncInfo::md5() const { 903 | // @@protoc_insertion_point(field_get:filesync.SyncInfo.MD5) 904 | return md5_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 905 | } 906 | inline void SyncInfo::set_md5(const ::std::string& value) { 907 | set_has_md5(); 908 | md5_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 909 | // @@protoc_insertion_point(field_set:filesync.SyncInfo.MD5) 910 | } 911 | inline void SyncInfo::set_md5(const char* value) { 912 | set_has_md5(); 913 | md5_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 914 | // @@protoc_insertion_point(field_set_char:filesync.SyncInfo.MD5) 915 | } 916 | inline void SyncInfo::set_md5(const char* value, size_t size) { 917 | set_has_md5(); 918 | md5_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 919 | ::std::string(reinterpret_cast(value), size)); 920 | // @@protoc_insertion_point(field_set_pointer:filesync.SyncInfo.MD5) 921 | } 922 | inline ::std::string* SyncInfo::mutable_md5() { 923 | set_has_md5(); 924 | // @@protoc_insertion_point(field_mutable:filesync.SyncInfo.MD5) 925 | return md5_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 926 | } 927 | inline ::std::string* SyncInfo::release_md5() { 928 | // @@protoc_insertion_point(field_release:filesync.SyncInfo.MD5) 929 | clear_has_md5(); 930 | return md5_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 931 | } 932 | inline void SyncInfo::set_allocated_md5(::std::string* md5) { 933 | if (md5 != NULL) { 934 | set_has_md5(); 935 | } else { 936 | clear_has_md5(); 937 | } 938 | md5_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), md5); 939 | // @@protoc_insertion_point(field_set_allocated:filesync.SyncInfo.MD5) 940 | } 941 | 942 | // ------------------------------------------------------------------- 943 | 944 | // SignIn 945 | 946 | // required string username = 1; 947 | inline bool SignIn::has_username() const { 948 | return (_has_bits_[0] & 0x00000001u) != 0; 949 | } 950 | inline void SignIn::set_has_username() { 951 | _has_bits_[0] |= 0x00000001u; 952 | } 953 | inline void SignIn::clear_has_username() { 954 | _has_bits_[0] &= ~0x00000001u; 955 | } 956 | inline void SignIn::clear_username() { 957 | username_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 958 | clear_has_username(); 959 | } 960 | inline const ::std::string& SignIn::username() const { 961 | // @@protoc_insertion_point(field_get:filesync.SignIn.username) 962 | return username_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 963 | } 964 | inline void SignIn::set_username(const ::std::string& value) { 965 | set_has_username(); 966 | username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 967 | // @@protoc_insertion_point(field_set:filesync.SignIn.username) 968 | } 969 | inline void SignIn::set_username(const char* value) { 970 | set_has_username(); 971 | username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 972 | // @@protoc_insertion_point(field_set_char:filesync.SignIn.username) 973 | } 974 | inline void SignIn::set_username(const char* value, size_t size) { 975 | set_has_username(); 976 | username_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 977 | ::std::string(reinterpret_cast(value), size)); 978 | // @@protoc_insertion_point(field_set_pointer:filesync.SignIn.username) 979 | } 980 | inline ::std::string* SignIn::mutable_username() { 981 | set_has_username(); 982 | // @@protoc_insertion_point(field_mutable:filesync.SignIn.username) 983 | return username_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 984 | } 985 | inline ::std::string* SignIn::release_username() { 986 | // @@protoc_insertion_point(field_release:filesync.SignIn.username) 987 | clear_has_username(); 988 | return username_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 989 | } 990 | inline void SignIn::set_allocated_username(::std::string* username) { 991 | if (username != NULL) { 992 | set_has_username(); 993 | } else { 994 | clear_has_username(); 995 | } 996 | username_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), username); 997 | // @@protoc_insertion_point(field_set_allocated:filesync.SignIn.username) 998 | } 999 | 1000 | // required string password = 2; 1001 | inline bool SignIn::has_password() const { 1002 | return (_has_bits_[0] & 0x00000002u) != 0; 1003 | } 1004 | inline void SignIn::set_has_password() { 1005 | _has_bits_[0] |= 0x00000002u; 1006 | } 1007 | inline void SignIn::clear_has_password() { 1008 | _has_bits_[0] &= ~0x00000002u; 1009 | } 1010 | inline void SignIn::clear_password() { 1011 | password_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1012 | clear_has_password(); 1013 | } 1014 | inline const ::std::string& SignIn::password() const { 1015 | // @@protoc_insertion_point(field_get:filesync.SignIn.password) 1016 | return password_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1017 | } 1018 | inline void SignIn::set_password(const ::std::string& value) { 1019 | set_has_password(); 1020 | password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 1021 | // @@protoc_insertion_point(field_set:filesync.SignIn.password) 1022 | } 1023 | inline void SignIn::set_password(const char* value) { 1024 | set_has_password(); 1025 | password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 1026 | // @@protoc_insertion_point(field_set_char:filesync.SignIn.password) 1027 | } 1028 | inline void SignIn::set_password(const char* value, size_t size) { 1029 | set_has_password(); 1030 | password_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 1031 | ::std::string(reinterpret_cast(value), size)); 1032 | // @@protoc_insertion_point(field_set_pointer:filesync.SignIn.password) 1033 | } 1034 | inline ::std::string* SignIn::mutable_password() { 1035 | set_has_password(); 1036 | // @@protoc_insertion_point(field_mutable:filesync.SignIn.password) 1037 | return password_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1038 | } 1039 | inline ::std::string* SignIn::release_password() { 1040 | // @@protoc_insertion_point(field_release:filesync.SignIn.password) 1041 | clear_has_password(); 1042 | return password_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1043 | } 1044 | inline void SignIn::set_allocated_password(::std::string* password) { 1045 | if (password != NULL) { 1046 | set_has_password(); 1047 | } else { 1048 | clear_has_password(); 1049 | } 1050 | password_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), password); 1051 | // @@protoc_insertion_point(field_set_allocated:filesync.SignIn.password) 1052 | } 1053 | 1054 | // ------------------------------------------------------------------- 1055 | 1056 | // Init 1057 | 1058 | // repeated .filesync.SyncInfo info = 3; 1059 | inline int Init::info_size() const { 1060 | return info_.size(); 1061 | } 1062 | inline void Init::clear_info() { 1063 | info_.Clear(); 1064 | } 1065 | inline const ::filesync::SyncInfo& Init::info(int index) const { 1066 | // @@protoc_insertion_point(field_get:filesync.Init.info) 1067 | return info_.Get(index); 1068 | } 1069 | inline ::filesync::SyncInfo* Init::mutable_info(int index) { 1070 | // @@protoc_insertion_point(field_mutable:filesync.Init.info) 1071 | return info_.Mutable(index); 1072 | } 1073 | inline ::filesync::SyncInfo* Init::add_info() { 1074 | // @@protoc_insertion_point(field_add:filesync.Init.info) 1075 | return info_.Add(); 1076 | } 1077 | inline ::google::protobuf::RepeatedPtrField< ::filesync::SyncInfo >* 1078 | Init::mutable_info() { 1079 | // @@protoc_insertion_point(field_mutable_list:filesync.Init.info) 1080 | return &info_; 1081 | } 1082 | inline const ::google::protobuf::RepeatedPtrField< ::filesync::SyncInfo >& 1083 | Init::info() const { 1084 | // @@protoc_insertion_point(field_list:filesync.Init.info) 1085 | return info_; 1086 | } 1087 | 1088 | // ------------------------------------------------------------------- 1089 | 1090 | // SendFile 1091 | 1092 | // required int32 id = 1; 1093 | inline bool SendFile::has_id() const { 1094 | return (_has_bits_[0] & 0x00000001u) != 0; 1095 | } 1096 | inline void SendFile::set_has_id() { 1097 | _has_bits_[0] |= 0x00000001u; 1098 | } 1099 | inline void SendFile::clear_has_id() { 1100 | _has_bits_[0] &= ~0x00000001u; 1101 | } 1102 | inline void SendFile::clear_id() { 1103 | id_ = 0; 1104 | clear_has_id(); 1105 | } 1106 | inline ::google::protobuf::int32 SendFile::id() const { 1107 | // @@protoc_insertion_point(field_get:filesync.SendFile.id) 1108 | return id_; 1109 | } 1110 | inline void SendFile::set_id(::google::protobuf::int32 value) { 1111 | set_has_id(); 1112 | id_ = value; 1113 | // @@protoc_insertion_point(field_set:filesync.SendFile.id) 1114 | } 1115 | 1116 | // required string filename = 2; 1117 | inline bool SendFile::has_filename() const { 1118 | return (_has_bits_[0] & 0x00000002u) != 0; 1119 | } 1120 | inline void SendFile::set_has_filename() { 1121 | _has_bits_[0] |= 0x00000002u; 1122 | } 1123 | inline void SendFile::clear_has_filename() { 1124 | _has_bits_[0] &= ~0x00000002u; 1125 | } 1126 | inline void SendFile::clear_filename() { 1127 | filename_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1128 | clear_has_filename(); 1129 | } 1130 | inline const ::std::string& SendFile::filename() const { 1131 | // @@protoc_insertion_point(field_get:filesync.SendFile.filename) 1132 | return filename_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1133 | } 1134 | inline void SendFile::set_filename(const ::std::string& value) { 1135 | set_has_filename(); 1136 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 1137 | // @@protoc_insertion_point(field_set:filesync.SendFile.filename) 1138 | } 1139 | inline void SendFile::set_filename(const char* value) { 1140 | set_has_filename(); 1141 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 1142 | // @@protoc_insertion_point(field_set_char:filesync.SendFile.filename) 1143 | } 1144 | inline void SendFile::set_filename(const char* value, size_t size) { 1145 | set_has_filename(); 1146 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 1147 | ::std::string(reinterpret_cast(value), size)); 1148 | // @@protoc_insertion_point(field_set_pointer:filesync.SendFile.filename) 1149 | } 1150 | inline ::std::string* SendFile::mutable_filename() { 1151 | set_has_filename(); 1152 | // @@protoc_insertion_point(field_mutable:filesync.SendFile.filename) 1153 | return filename_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1154 | } 1155 | inline ::std::string* SendFile::release_filename() { 1156 | // @@protoc_insertion_point(field_release:filesync.SendFile.filename) 1157 | clear_has_filename(); 1158 | return filename_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1159 | } 1160 | inline void SendFile::set_allocated_filename(::std::string* filename) { 1161 | if (filename != NULL) { 1162 | set_has_filename(); 1163 | } else { 1164 | clear_has_filename(); 1165 | } 1166 | filename_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), filename); 1167 | // @@protoc_insertion_point(field_set_allocated:filesync.SendFile.filename) 1168 | } 1169 | 1170 | // ------------------------------------------------------------------- 1171 | 1172 | // IsControl 1173 | 1174 | // required int32 id = 1; 1175 | inline bool IsControl::has_id() const { 1176 | return (_has_bits_[0] & 0x00000001u) != 0; 1177 | } 1178 | inline void IsControl::set_has_id() { 1179 | _has_bits_[0] |= 0x00000001u; 1180 | } 1181 | inline void IsControl::clear_has_id() { 1182 | _has_bits_[0] &= ~0x00000001u; 1183 | } 1184 | inline void IsControl::clear_id() { 1185 | id_ = 0; 1186 | clear_has_id(); 1187 | } 1188 | inline ::google::protobuf::int32 IsControl::id() const { 1189 | // @@protoc_insertion_point(field_get:filesync.IsControl.id) 1190 | return id_; 1191 | } 1192 | inline void IsControl::set_id(::google::protobuf::int32 value) { 1193 | set_has_id(); 1194 | id_ = value; 1195 | // @@protoc_insertion_point(field_set:filesync.IsControl.id) 1196 | } 1197 | 1198 | // ------------------------------------------------------------------- 1199 | 1200 | // FileInfo 1201 | 1202 | // required int32 size = 1; 1203 | inline bool FileInfo::has_size() const { 1204 | return (_has_bits_[0] & 0x00000001u) != 0; 1205 | } 1206 | inline void FileInfo::set_has_size() { 1207 | _has_bits_[0] |= 0x00000001u; 1208 | } 1209 | inline void FileInfo::clear_has_size() { 1210 | _has_bits_[0] &= ~0x00000001u; 1211 | } 1212 | inline void FileInfo::clear_size() { 1213 | size_ = 0; 1214 | clear_has_size(); 1215 | } 1216 | inline ::google::protobuf::int32 FileInfo::size() const { 1217 | // @@protoc_insertion_point(field_get:filesync.FileInfo.size) 1218 | return size_; 1219 | } 1220 | inline void FileInfo::set_size(::google::protobuf::int32 value) { 1221 | set_has_size(); 1222 | size_ = value; 1223 | // @@protoc_insertion_point(field_set:filesync.FileInfo.size) 1224 | } 1225 | 1226 | // required string filename = 2; 1227 | inline bool FileInfo::has_filename() const { 1228 | return (_has_bits_[0] & 0x00000002u) != 0; 1229 | } 1230 | inline void FileInfo::set_has_filename() { 1231 | _has_bits_[0] |= 0x00000002u; 1232 | } 1233 | inline void FileInfo::clear_has_filename() { 1234 | _has_bits_[0] &= ~0x00000002u; 1235 | } 1236 | inline void FileInfo::clear_filename() { 1237 | filename_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1238 | clear_has_filename(); 1239 | } 1240 | inline const ::std::string& FileInfo::filename() const { 1241 | // @@protoc_insertion_point(field_get:filesync.FileInfo.filename) 1242 | return filename_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1243 | } 1244 | inline void FileInfo::set_filename(const ::std::string& value) { 1245 | set_has_filename(); 1246 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); 1247 | // @@protoc_insertion_point(field_set:filesync.FileInfo.filename) 1248 | } 1249 | inline void FileInfo::set_filename(const char* value) { 1250 | set_has_filename(); 1251 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 1252 | // @@protoc_insertion_point(field_set_char:filesync.FileInfo.filename) 1253 | } 1254 | inline void FileInfo::set_filename(const char* value, size_t size) { 1255 | set_has_filename(); 1256 | filename_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), 1257 | ::std::string(reinterpret_cast(value), size)); 1258 | // @@protoc_insertion_point(field_set_pointer:filesync.FileInfo.filename) 1259 | } 1260 | inline ::std::string* FileInfo::mutable_filename() { 1261 | set_has_filename(); 1262 | // @@protoc_insertion_point(field_mutable:filesync.FileInfo.filename) 1263 | return filename_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1264 | } 1265 | inline ::std::string* FileInfo::release_filename() { 1266 | // @@protoc_insertion_point(field_release:filesync.FileInfo.filename) 1267 | clear_has_filename(); 1268 | return filename_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); 1269 | } 1270 | inline void FileInfo::set_allocated_filename(::std::string* filename) { 1271 | if (filename != NULL) { 1272 | set_has_filename(); 1273 | } else { 1274 | clear_has_filename(); 1275 | } 1276 | filename_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), filename); 1277 | // @@protoc_insertion_point(field_set_allocated:filesync.FileInfo.filename) 1278 | } 1279 | 1280 | #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS 1281 | // ------------------------------------------------------------------- 1282 | 1283 | // ------------------------------------------------------------------- 1284 | 1285 | // ------------------------------------------------------------------- 1286 | 1287 | // ------------------------------------------------------------------- 1288 | 1289 | // ------------------------------------------------------------------- 1290 | 1291 | 1292 | // @@protoc_insertion_point(namespace_scope) 1293 | 1294 | } // namespace filesync 1295 | 1296 | // @@protoc_insertion_point(global_scope) 1297 | 1298 | #endif // PROTOBUF_filesync_2eproto__INCLUDED 1299 | -------------------------------------------------------------------------------- /protobuf/filesync.proto: -------------------------------------------------------------------------------- 1 | package filesync; 2 | message SyncInfo 3 | {//告知哪些文件有修改 4 | required int32 id = 1; //0是创建文件夹,1是create文件,2是modify,3是删除,4是重命名 5 | required string filename = 2; //文件名(包含相对顶层文件夹的路径) 6 | optional string newFilename = 3; //新文件名(用于重命名) 7 | optional int32 size = 4; //文件大小 8 | optional string MD5 = 5; //文件的md5 9 | } 10 | 11 | message SignIn 12 | {//登录 13 | required string username = 1; 14 | required string password = 2; 15 | } 16 | 17 | message Init 18 | {//初始化 19 | repeated SyncInfo info = 3; 20 | } 21 | 22 | message SendFile 23 | {//告知哪些文件需要发送或接受 24 | required int32 id = 1; //消息标识,0:服务器传给客户端,1:客户端传给服务器 25 | required string filename = 2; 26 | } 27 | 28 | //服务端没有,客户端有的【空洞】 29 | message HoleInfo 30 | { 31 | required int32 start = 1; 32 | required int32 length = 2; 33 | } 34 | 35 | message Sendfile_Rsync 36 | { 37 | repeated HoleInfo; 38 | } 39 | 40 | message IsControl 41 | {//这是传输通道 42 | required int32 id = 1; 43 | } 44 | 45 | //客户端向服务端发送rsync所需的各块的adler32和md5 46 | message BlockInfo 47 | { 48 | required int32 adler32 = 1; 49 | required int32 md5 = 2; 50 | required int32 offset = 3; //此数据块在原文件中的位置 51 | } 52 | 53 | message RsyncInfo 54 | { 55 | required string filename = 1; 56 | required repeated BlockInfo = 2; 57 | } 58 | /*****以上是控制通道负责*********/ 59 | /*****以下是文件传输通道********/ 60 | message FileInfo 61 | { 62 | required int32 size = 1; //文件大小 63 | required string filename = 2;//文件名 64 | } 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /rsync.cpp: -------------------------------------------------------------------------------- 1 | #include "rsync.h" 2 | #include 3 | #include 4 | #include "sysutil.h" 5 | using namespace std; 6 | 7 | Rsync::Rsync(string &filename):filename(filename) 8 | { 9 | 10 | } 11 | 12 | void Rsync::addHashItem(int adler32, DataBlockPtr dataBlockPtr) 13 | { 14 | adler_blockMaps[adler32] = dataBlockPtr; 15 | } 16 | //找到匹配的数据块后就会从adler_blockMaps中删除,所以最后adler_blockMaps剩下的就是空洞链表 17 | void Rsync::calRsync() 18 | { 19 | int ad;//adler32和md5 20 | string md; 21 | int firstCh,lastCh; 22 | FILE *fp = fopen(filename.c_str(),"rb"); 23 | /*获取需要计算的块数,并分块计算,输出到文件*/ 24 | fseek(fp, 0, SEEK_END);//获取文件尾 25 | int end = ftell(fp); 26 | int size = end / BLOCK_SIZE; 27 | rewind(fp);//重置文件指针 28 | char* buff = (char*)malloc(sizeof(char)*(BLOCK_SIZE+1 )); 29 | for(int i=0;isecond->md5) 39 | { 40 | DataBlockPtr dataBlockPtr(new DataBlock(i*BLOCK_SIZE, 41 | it->second->s_offset,ad,md)); 42 | dataList.push_back(dataBlockPtr); 43 | adler_blockMaps.erase(it); 44 | } 45 | else 46 | goto roll; 47 | } 48 | else 49 | { 50 | roll: 51 | for (int in = 0; in < BLOCK_SIZE; in++) 52 | { 53 | moveCh(&firstCh, &lastCh, fp,buff); 54 | ad = sysutil::adler32_rolling_checksum(ad, BLOCK_SIZE, firstCh, lastCh);//滚动后的校验和 55 | if (in == BLOCK_SIZE - 1) 56 | { 57 | fseek(fp, -BLOCK_SIZE, SEEK_CUR); 58 | break;//跳出本次循环 59 | } 60 | auto it = adler_blockMaps.find(ad); 61 | if (it!=adler_blockMaps.end()) 62 | { 63 | md = sysutil::getStringMd5(buff); 64 | if (it->second->md5 == md)//如果MD5也匹配 65 | { 66 | DataBlockPtr dataBlockPtr(new DataBlock(in+i*BLOCK_SIZE, 67 | it->second->s_offset,ad,md)); 68 | dataList.push_back(dataBlockPtr); 69 | break;//跳出本次循环 70 | } 71 | adler_blockMaps.erase(it); 72 | } 73 | } 74 | } 75 | } 76 | fclose(fp); 77 | //生成空洞链表 78 | for(auto it = adler_blockMaps.begin();it!=adler_blockMaps.end();++it) 79 | { 80 | HoleInfoPtr holeInfoPtr(new HoleInfo(it->second->s_offset,BLOCK_SIZE)); 81 | holeList.push_back(holeInfoPtr); 82 | } 83 | holeList.sort([](HoleInfoPtr p1,HoleInfoPtr p2){ 84 | return p1->offset < p2->offset; 85 | }); 86 | dataList.sort([](DataBlockPtr p1,DataBlockPtr p2){ 87 | return p1->s_offset < p2->s_offset; 88 | }); 89 | free(buff); 90 | } 91 | 92 | void Rsync::reconstruct(char *data, int len,string temFilename) 93 | { 94 | FILE *s_fp = fopen(filename.c_str(),"rb"); 95 | FILE *t_fp = fopen(temFilename.c_str(),"wb"); 96 | char buf[BLOCK_SIZE+1]; 97 | while(len > BLOCK_SIZE) 98 | { 99 | auto it_hole = holeList.begin(); 100 | auto it_data = dataList.begin(); 101 | if(!dataList.empty() && (*it_data)->s_offset < (*it_hole)->offset) 102 | {//从已有文件复制过去 103 | fseek(s_fp,(*it_data)->t_offset,SEEK_SET); 104 | fread(buf,sizeof(char),BLOCK_SIZE,s_fp); 105 | fwrite(buf,sizeof(char),BLOCK_SIZE,t_fp); 106 | dataList.pop_front(); 107 | } 108 | else 109 | { 110 | fwrite(data,sizeof(char),BLOCK_SIZE,t_fp); 111 | holeList.pop_front(); 112 | len -= BLOCK_SIZE; 113 | data += BLOCK_SIZE; 114 | } 115 | } 116 | while(!dataList.empty()) 117 | {//从已有文件复制过去 118 | auto it_data = dataList.begin(); 119 | fseek(s_fp,(*it_data)->t_offset,SEEK_SET); 120 | fread(buf,sizeof(char),BLOCK_SIZE,s_fp); 121 | fwrite(buf,sizeof(char),BLOCK_SIZE,t_fp); 122 | dataList.pop_front(); 123 | } 124 | //不足一个BLOCK_SIZE的都写到文件尾 125 | fwrite(data,sizeof(char),len,t_fp); 126 | fclose(s_fp); 127 | fclose(t_fp); 128 | } 129 | 130 | //将fp指针向后挪一个字节 131 | void Rsync::moveCh(int* firstCh, int* lastCh, FILE * fp , char * buff) 132 | { 133 | fseek(fp, -BLOCK_SIZE, SEEK_CUR); 134 | *firstCh = fgetc(fp); 135 | fread(buff, sizeof(char), BLOCK_SIZE, fp); 136 | *lastCh = buff[BLOCK_SIZE-1]; 137 | } 138 | -------------------------------------------------------------------------------- /rsync.h: -------------------------------------------------------------------------------- 1 | #ifndef RSYNC_H 2 | #define RSYNC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | //文件数据块,即服务端和客户端都有的块 11 | struct DataBlock 12 | { 13 | int t_offset; //此数据块在服务端文件中的offset 14 | int s_offset; //此数据块在客户端文件中的offset 15 | int adler32; 16 | std::string md5; 17 | DataBlock(int t_offset,int s_offset,int adler32,std::string &md5): 18 | t_offset(t_offset),s_offset(s_offset),adler32(adler32),md5(md5) {} 19 | }; 20 | //空洞块,即服务端没有客户端有的块 21 | struct HoleInfo 22 | { 23 | int offset; 24 | int len; 25 | HoleInfo(int offset,int len):offset(offset),len(len) {} 26 | }; 27 | 28 | typedef std::shared_ptr HoleInfoPtr; 29 | typedef std::shared_ptr DataBlockPtr; 30 | 31 | class Rsync 32 | { 33 | public: 34 | Rsync(std::string &filename); 35 | //添加到adler_blockMaps 36 | void addHashItem(int adler32,DataBlockPtr dataBlockPtr); 37 | //添加完adler_blockMaps后执行Rsync算法,生成空洞链表 38 | void calRsync(); 39 | //将空洞信息发送给客户端 40 | void sendHoleInfo(); 41 | //生成新文件 42 | void reconstruct(char *data, int len, std::__cxx11::string temFilename); 43 | 44 | //仅供测试 45 | std::list getHoleList() {return holeList;} 46 | private: 47 | std::string filename; 48 | static const int BLOCK_SIZE = 2; 49 | void rollChecksum(); 50 | //空洞链表 51 | std::list holeList; 52 | //服务端和客户端都有的数据块的链表,offset以服务端为准 53 | std::list dataList; 54 | //客户端的adler32和数据块的映射 55 | std::unordered_map adler_blockMaps; 56 | unsigned int adler32(char *data, int len); 57 | unsigned int adler32_rolling_checksum(unsigned int csum, int len, char c1, char c2); 58 | void moveCh(int *firstCh, int *lastCh, FILE *fp, char *buff); 59 | }; 60 | 61 | #endif // RSYNC_H 62 | -------------------------------------------------------------------------------- /socket.cpp: -------------------------------------------------------------------------------- 1 | #include "socket.h" 2 | #include 3 | #include 4 | #include 5 | 6 | TcpSocket::TcpSocket() 7 | { 8 | //初始化Socket 9 | if( (socket_fd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1 ) 10 | CHEN_LOG(ERROR,"create socket error"); 11 | } 12 | 13 | TcpSocket::~TcpSocket() 14 | { 15 | ::close(socket_fd); 16 | } 17 | 18 | void TcpSocket::bind(int port) 19 | { 20 | memset(&servaddr, 0, sizeof(servaddr)); 21 | servaddr.sin_family = AF_INET; 22 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址。 23 | servaddr.sin_port = htons(port);//设置的端口为DEFAULT_PORT 24 | //将本地地址绑定到所创建的套接字上 25 | if(::bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) 26 | { 27 | CHEN_LOG(ERROR,"bind error"); 28 | } 29 | } 30 | 31 | void TcpSocket::listen() 32 | { 33 | //开始监听是否有客户端连接 34 | if(::listen(socket_fd, SOMAXCONN) == -1) 35 | { 36 | CHEN_LOG(ERROR,"listen error"); 37 | } 38 | } 39 | 40 | int TcpSocket::accept() 41 | { 42 | int connect_fd; 43 | if( (connect_fd = ::accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1) 44 | { 45 | CHEN_LOG(ERROR,"accept error"); 46 | } 47 | return connect_fd; 48 | } 49 | -------------------------------------------------------------------------------- /socket.h: -------------------------------------------------------------------------------- 1 | #ifndef SOCKET_H 2 | #define SOCKET_H 3 | #include 4 | #include "common.h" 5 | using namespace std; 6 | 7 | class TcpSocket 8 | { 9 | public: 10 | TcpSocket(); 11 | ~TcpSocket(); 12 | void bind(int port); 13 | void listen(); 14 | int accept(); 15 | void shutdown(); 16 | private: 17 | struct sockaddr_in servaddr; 18 | int socket_fd; 19 | string ip; //对方的ip和端口 20 | int port; 21 | }; 22 | 23 | #endif // SOCKET_H 24 | -------------------------------------------------------------------------------- /str_tool.cpp: -------------------------------------------------------------------------------- 1 | #include "str_tool.h" 2 | 3 | /** 4 | * 去除换行符 5 | * @param str 要处理的字符串 6 | */ 7 | void str_trim_crlf(char *str) 8 | { 9 | char *p = &str[strlen(str)-1]; 10 | while (*p == '\r' || *p == '\n') 11 | *p-- = '\0'; 12 | 13 | } 14 | /** 15 | * 分割字符串,分割后两个子串不包含c 16 | * @param str 要处理的字符串 17 | * @param left 左子字符串 18 | * @param right 右子字符串 19 | * @param c 分割标志 20 | */ 21 | void str_split(char *str , char *left, char *right, char c) 22 | { 23 | char *p = strchr(str, c); 24 | if (p == NULL) 25 | strcpy(left, str); 26 | else 27 | { 28 | *p = '\0'; 29 | strcpy(left, str); 30 | strcpy(right, p+1); 31 | } 32 | } 33 | /** 34 | * 去除首尾空格 35 | * @param str 要处理的字符串 36 | * @return 返回处理后的字符串 37 | */ 38 | char *str_delspace(char *str) 39 | { 40 | char* end,*sp,*ep;//结尾指针,两个游标 41 | size_t len;//用于保存长度长度 42 | sp = str;//sp指针首先指向行首 43 | end = ep = str + strlen(str) -1;//end指针指向结尾 44 | //从行首开始去空格 45 | while(sp <= end && isspace(*sp))//是空格返回非零 46 | sp++;//移动sp指针直到指向的不是空格 47 | //从行尾去除空格 48 | while(ep >= sp && isspace(*ep)) 49 | ep--; 50 | len = (ep < sp)? 0 :(ep - sp)+1;//计算长度+1,指向换行符 51 | sp[len] = '\0';//换行符置为'\0' 52 | return sp; 53 | } 54 | 55 | /** 56 | * 将字符串转换为大写 57 | * @param str 要处理的字符串 58 | */ 59 | void str_upper(char *str) 60 | { 61 | while (*str) 62 | { 63 | *str = toupper(*str); 64 | str++; 65 | } 66 | } 67 | 68 | /** 69 | * 字符串表示的8进制数转换为unsigned int 70 | * @param str 要处理的字符串 71 | * @return unsigned int类型的整数 72 | */ 73 | unsigned int str_octal_to_uint(char *str) 74 | { 75 | unsigned int result = 0; 76 | int seen_non_zero_digit = 0; 77 | 78 | while (*str) 79 | { 80 | int digit = *str; 81 | if (!isdigit(digit) || digit > '7')//8进制数最大值为7 82 | break; 83 | 84 | if (digit != '0') //找到第一个不为0的字符 85 | seen_non_zero_digit = 1; 86 | 87 | if (seen_non_zero_digit) 88 | { 89 | result <<= 3; //乘8 90 | result += (digit - '0'); 91 | } 92 | str++; 93 | } 94 | return result; 95 | } 96 | /** 97 | * 将字符串转换为long long类型的数 98 | * @param str 要处理的字符串 99 | * @return long long类型的数 100 | */ 101 | long long str_to_longlong(const char *str) 102 | { 103 | //return atoll(str); 104 | /* long long result = 0; 105 | long long mult = 1; 106 | unsigned int len = strlen(str); 107 | unsigned int i; 108 | 109 | if (len > 15) 110 | return 0; 111 | 112 | 113 | for (i=0; i '9') 118 | return 0; 119 | 120 | val = ch - '0'; 121 | val *= mult; 122 | result += val; 123 | mult *= 10; 124 | } 125 | */ 126 | 127 | long long result = 0; 128 | long long mult = 1; 129 | unsigned int len = strlen(str); 130 | int i; 131 | 132 | if (len > 15) 133 | return 0; 134 | 135 | for (i=len-1; i>=0; i--) 136 | { 137 | char ch = str[i]; 138 | long long val; 139 | if (ch < '0' || ch > '9') 140 | return 0; 141 | 142 | val = ch - '0'; 143 | val *= mult; 144 | result += val; 145 | mult *= 10; 146 | } 147 | 148 | return result; 149 | } 150 | -------------------------------------------------------------------------------- /str_tool.h: -------------------------------------------------------------------------------- 1 | #ifndef STR_TOOL_H 2 | #define STR_TOOL_H 3 | #include "common.h" 4 | 5 | using namespace std; 6 | //去除行首尾的空格和换行符 7 | void str_trim_crlf(char *str); 8 | void str_split(char *str , char *left, char *right, char c); 9 | char *str_delspace(char *str); 10 | void str_upper(char *str); 11 | unsigned int str_octal_to_uint(char *str); 12 | long long str_to_longlong(const char *str); 13 | 14 | #endif // STR_TOOL_H 15 | -------------------------------------------------------------------------------- /syncserver.cpp: -------------------------------------------------------------------------------- 1 | #include "syncserver.h" 2 | #include "sysutil.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | SyncServer::SyncServer(muduo::net::EventLoop *loop,int port) 21 | : serverAddr(port), 22 | server_(loop,serverAddr,"syncServer"), 23 | pc(ParseConfig::getInstance()) 24 | { 25 | pc->loadfile(); 26 | rootDir = pc->getSyncRoot(); 27 | initMd5(rootDir); 28 | CHEN_LOG(DEBUG,"MD5 completed"); 29 | server_.setConnectionCallback(boost::bind(&SyncServer::onConnection,this,_1)); 30 | server_.setMessageCallback(boost::bind(&SyncServer::onMessage,this,_1,_2,_3)); 31 | 32 | codec.registerCallback(std::bind(&SyncServer::onSignIn,this, 33 | std::placeholders::_1,std::placeholders::_2)); 34 | codec.registerCallback(std::bind(&SyncServer::onInit,this, 35 | std::placeholders::_1,std::placeholders::_2)); 36 | codec.registerCallback(std::bind(&SyncServer::onSyncInfo,this, 37 | std::placeholders::_1,std::placeholders::_2)); 38 | codec.registerCallback(std::bind(&SyncServer::onFileInfo,this, 39 | std::placeholders::_1,std::placeholders::_2)); 40 | } 41 | //接收到连接,初始化conn相关的数据结构 42 | void SyncServer::onConnection(const muduo::net::TcpConnectionPtr &conn) 43 | { 44 | if(conn->connected()) 45 | { 46 | Info_ConnPtr info_ptr(new Info_Conn ); 47 | conn->setContext(info_ptr); 48 | } 49 | else if(conn->disconnected()) 50 | {//连接断开 51 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 52 | auto it_userMaps = userMaps.find(info_ptr->username); 53 | if(it_userMaps != userMaps.end()) 54 | userMaps.erase(it_userMaps); 55 | auto it_queueMaps = sendListMaps.find(info_ptr->username); 56 | if(it_queueMaps != sendListMaps.end()) 57 | sendListMaps.erase(it_queueMaps); 58 | } 59 | } 60 | //接收到原始的数据包后的处理 61 | void SyncServer::onMessage(const muduo::net::TcpConnectionPtr &conn, 62 | muduo::net::Buffer *buf,muduo::Timestamp receiveTime) 63 | { 64 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 65 | if(info_ptr->isRecving) 66 | {//是文件数据 67 | recvFile(conn,info_ptr); 68 | } 69 | 70 | else 71 | {//是proto中定义的消息 72 | codec.parse(conn,buf); 73 | } 74 | } 75 | //用户登录时,更新userMap,并根据此用户的连接次数设置此conn的类型 76 | void SyncServer::onSignIn(const muduo::net::TcpConnectionPtr &conn, const SignInPtr &message) 77 | { 78 | string username = message->username(); 79 | string password = message->password(); 80 | if(!pc->checkUser(username,password)) 81 | {//帐号错误直接关闭连接 82 | CHEN_LOG(INFO,"user invalid"); 83 | conn->forceClose(); 84 | return; 85 | } 86 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 87 | info_ptr->username = username; 88 | auto it = userMaps.find(username); 89 | if(it != userMaps.end()) 90 | { 91 | it->second.push_back(conn); 92 | info_ptr->type = ConType::DATA; 93 | } 94 | else 95 | {//此用户第一个连接的socket设置为控制通道 96 | info_ptr->type = CONTROL; 97 | Con_Vec vec; 98 | vec.push_back(conn); 99 | { 100 | muduo::MutexLockGuard mutexLock(userMaps_mutex); 101 | userMaps.insert(make_pair(username,std::move(vec))); 102 | } 103 | //为此客户端初始化发送队列 104 | TaskList emptyQueue; 105 | { 106 | muduo::MutexLockGuard mutexLock(sendListMaps_mutex); 107 | sendListMaps.insert(make_pair(username,emptyQueue)); 108 | } 109 | //告知客户端这是控制通道 110 | filesync::IsControl msg; 111 | msg.set_id(1); 112 | std::string send_str = Codec::enCode(msg); 113 | conn->send(send_str); 114 | } 115 | } 116 | 117 | 118 | //客户端第一次上线发过来文件信息 119 | void SyncServer::onInit(const muduo::net::TcpConnectionPtr &conn,const InitPtr &message) 120 | { 121 | 122 | CHEN_LOG(DEBUG,"INIT RECEIVE"); 123 | vector clientFiles; 124 | for(int i=0;iinfo_size();i++) 125 | { 126 | filesync::SyncInfo info = message->info(i); 127 | string filename = info.filename(); 128 | string localname = rootDir+filename; 129 | SyncInfoPtr tmpPtr(new filesync::SyncInfo); 130 | tmpPtr->set_filename(filename); 131 | tmpPtr->set_md5(info.md5()); 132 | tmpPtr->set_id(info.id()); 133 | onSyncInfo(conn,tmpPtr); 134 | clientFiles.push_back(localname); 135 | } 136 | syncToClient(conn,rootDir,clientFiles); 137 | } 138 | //收到客户端发来的修改信息 139 | void SyncServer::onSyncInfo(const muduo::net::TcpConnectionPtr &conn, 140 | const SyncInfoPtr &message) 141 | { 142 | int id = message->id(); 143 | string filename = message->filename(); 144 | string newFilename = message->newfilename(); 145 | string localname = rootDir+filename; 146 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 147 | switch(id) 148 | { 149 | case 0: 150 | {//创建文件夹 151 | if(::access(localname.c_str(),F_OK) != 0) 152 | mkdir(localname.c_str(),0666); 153 | break; 154 | } 155 | case 1: 156 | {//创建文件 157 | } 158 | case 2: 159 | {//文件内容修改 160 | { 161 | muduo::MutexLockGuard mutexLock(md5Maps_mutex); 162 | auto it = md5Maps.find(localname); 163 | if(it != md5Maps.end()) 164 | if(it->second == message->md5()) 165 | { 166 | break; //已有相同文件则跳过 167 | } 168 | md5Maps[localname] = message->md5(); 169 | } 170 | //向客户端发送sendfile命令 171 | filesync::SendFile msg; 172 | msg.set_id(1); 173 | msg.set_filename(filename); 174 | string cmd = codec.enCode(msg); 175 | CHEN_LOG(INFO,"command sendfile :----%s",filename.c_str()); 176 | conn->send(cmd); 177 | break; 178 | } 179 | case 3: 180 | {//删除文件 181 | { 182 | muduo::MutexLockGuard mutexLock(md5Maps_mutex); 183 | auto it = md5Maps.find(localname); 184 | if(it != md5Maps.end()) 185 | md5Maps.erase(it); //删除此文件的md5信息 186 | } 187 | if(access(localname.c_str(),F_OK) != 0) //文件不存在 188 | CHEN_LOG(INFO,"file %s don't exit",localname.c_str()); 189 | else 190 | { 191 | // CHEN_LOG(INFO,"remove file %s",localname.c_str()); 192 | char rmCmd[512]; 193 | sprintf(rmCmd,"rm -rf %s",localname.c_str()); 194 | system(rmCmd); 195 | } 196 | int sendsize = message->size(); 197 | if(sendsize > 0) 198 | {//客户端上传过程中文件被删除 199 | int pos = message->filename().find_last_of('/'); 200 | string parDir = message->filename().substr(0,pos+1); 201 | string subfile = message->filename().substr(pos+1); 202 | string filename = rootDir+parDir+"."+ info_ptr->username+subfile; 203 | Con_Vec conVec = userMaps[info_ptr->username]; 204 | for(auto it = conVec.begin();it != conVec.end();++it) 205 | { 206 | Info_ConnPtr info_ptr = boost::any_cast((*it)->getContext()); 207 | if(info_ptr->receiveFilename == filename && info_ptr->isRecving) 208 | { 209 | info_ptr->remainSize = sendsize-(info_ptr->totalSize-info_ptr->remainSize); 210 | info_ptr->totalSize = sendsize; 211 | info_ptr->isRemoved_receving = true; 212 | recvFile(*it,info_ptr); 213 | } 214 | } 215 | } 216 | handleRemove_sending(localname); 217 | 218 | break; 219 | } 220 | case 4: 221 | {//重命名 222 | if(rename(localname.c_str(),(rootDir+newFilename).c_str()) < 0) 223 | CHEN_LOG(WARN,"rename %s error",localname.c_str()); 224 | CHEN_LOG(DEBUG,"rename %s to %s",localname.c_str(), 225 | (rootDir+newFilename).c_str()); 226 | break; 227 | } 228 | } 229 | if(id!=1 && id!=2) 230 | {//发送给其它客户端 231 | { 232 | muduo::MutexLockGuard mutexLock(userMaps_mutex); 233 | for(auto it = userMaps.begin();it!=userMaps.end();++it) 234 | { 235 | if(it->first == info_ptr->username) 236 | continue; 237 | sysutil::send_SyncInfo(it->second[0],id,filename,newFilename); 238 | } 239 | } 240 | } 241 | } 242 | //解析fileInfo消息后的回调函数 243 | void SyncServer::onFileInfo(const muduo::net::TcpConnectionPtr &conn, 244 | const FileInfoPtr &message) 245 | { 246 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 247 | info_ptr->isRecving = true; 248 | //文件接收时以隐藏文件存储,隐藏文件名为XXX/.[username][filename] 249 | int pos = message->filename().find_last_of('/'); 250 | string parDir = message->filename().substr(0,pos+1); 251 | string subfile = message->filename().substr(pos+1); 252 | string filename = info_ptr->receiveFilename = rootDir+parDir+"."+ 253 | info_ptr->username.c_str()+subfile; 254 | CHEN_LOG(INFO,"temp file :%s",filename.c_str()); 255 | info_ptr->totalSize = info_ptr->remainSize = message->size(); 256 | //如果同名文件存在则删除 257 | if(access(filename.c_str(),F_OK) == 0) 258 | if(::remove(filename.c_str()) < 0) 259 | CHEN_LOG(ERROR,"remove error"); 260 | recvFile(conn,info_ptr); 261 | } 262 | 263 | //客户端接收过程中文件被删除 264 | void SyncServer::handleRemove_sending(string localname) 265 | { 266 | Con_Vec conVec = sendfileMaps[localname]; 267 | if(!conVec.empty()) 268 | { 269 | for(auto it:conVec) 270 | { 271 | Info_ConnPtr info_ptr = boost::any_cast(it->getContext()); 272 | if(!info_ptr->isIdle && info_ptr->sendFilename == localname) 273 | { 274 | info_ptr->isRemoved_sending = true; 275 | CHEN_LOG(INFO,"REMOVING SENDING FILE%s",localname.c_str()); 276 | } 277 | //从待发送列表中删除 278 | auto it_map = sendListMaps.find(info_ptr->username); 279 | for(auto it = it_map->second.begin();it!=it_map->second.end();) 280 | { 281 | if(it->first == localname) 282 | it_map->second.erase(it); 283 | else 284 | ++it; 285 | } 286 | } 287 | } 288 | } 289 | 290 | /** 291 | * @brief SyncServer::recvFile 从Buffer中接收文件数据,接收完发送给其它客户端 292 | * @param conn 293 | * @param info_ptr 294 | */ 295 | void SyncServer::recvFile(const muduo::net::TcpConnectionPtr &conn,Info_ConnPtr &info_ptr) 296 | { 297 | int len = conn->inputBuffer()->readableBytes(); 298 | if(len >= info_ptr->remainSize) 299 | {//文件接收完 300 | sysutil::fileRecvfromBuf(info_ptr->receiveFilename.c_str(), 301 | conn->inputBuffer()->peek(),info_ptr->remainSize); 302 | conn->inputBuffer()->retrieve(info_ptr->remainSize); 303 | info_ptr->isRecving = false; 304 | info_ptr->remainSize = 0; 305 | info_ptr->totalSize = 0; 306 | if(info_ptr->isRemoved_receving) 307 | remove(info_ptr->receiveFilename.c_str()); 308 | else 309 | { 310 | //将原文件删除,隐藏文件改名 311 | int pos = info_ptr->receiveFilename.find_last_of('/'); 312 | string parDir = info_ptr->receiveFilename.substr(0,pos+1); 313 | string subfile = info_ptr->receiveFilename.substr(pos+1); 314 | string filename = parDir+subfile.substr(info_ptr->username.size()+1); 315 | if(access(filename.c_str(),F_OK) == 0) 316 | if(::remove(filename.c_str()) < 0) 317 | CHEN_LOG(ERROR,"remove error"); 318 | if(rename(info_ptr->receiveFilename.c_str(),filename.c_str()) < 0) 319 | CHEN_LOG(ERROR,"rename %s error",info_ptr->receiveFilename.c_str()); 320 | CHEN_LOG(INFO,"receive file COMPLETED:%s",filename.c_str()); 321 | sendListMaps_mutex.lock(); 322 | //发送给其它客户端 323 | handleRemove_sending(filename);//将正在发送的同名文件取消发送 324 | for(auto it = sendListMaps.begin();it!=sendListMaps.end();++it) 325 | { 326 | if(it->first == info_ptr->username) 327 | { 328 | continue; 329 | } 330 | muduo::net::TcpConnectionPtr idleConn = getIdleConn(it->first); 331 | if(idleConn == nullptr) 332 | {//加入发送队列 333 | { 334 | it->second.push_back({filename,std::bind(&SyncServer::sendfileWithproto,this, 335 | std::placeholders::_1,filename) 336 | }); 337 | sendListMaps_mutex.unlock(); 338 | } 339 | } 340 | else 341 | { 342 | sendListMaps_mutex.unlock(); 343 | sendfileWithproto(idleConn,filename); 344 | } 345 | } 346 | sendListMaps_mutex.unlock(); 347 | } 348 | info_ptr->receiveFilename.clear(); 349 | info_ptr->md5.clear(); 350 | info_ptr->isRemoved_receving = false; 351 | //如果buffer还有数据则继续解析 352 | if(conn->inputBuffer()->readableBytes() > 0) 353 | onMessage(conn,conn->inputBuffer(),muduo::Timestamp::now()); 354 | } 355 | else 356 | { 357 | sysutil::fileRecvfromBuf(info_ptr->receiveFilename.c_str(), 358 | conn->inputBuffer()->peek(),len); 359 | conn->inputBuffer()->retrieve(len); 360 | info_ptr->remainSize -= len; 361 | } 362 | } 363 | 364 | 365 | /** 366 | * @brief sendfileWithproto 先发送fileInfo信息再发送文件内容,不能发送文件夹!! 367 | * 服务端不能和客户端一样阻塞写,要用网络库的接口,socket可写的时候调用回调函数写数据 368 | * @param conn 文件由此conn发出,此时conn已有context 369 | * @param localname 本地路径 370 | */ 371 | void SyncServer::sendfileWithproto(const muduo::net::TcpConnectionPtr &conn 372 | ,string &localname) 373 | { 374 | int fd = open(localname.c_str(),O_RDONLY); 375 | if(-1 == fd) 376 | { 377 | CHEN_LOG(INFO,"open file %s error",localname); 378 | return; 379 | } 380 | struct stat sbuf; 381 | fstat(fd,&sbuf); 382 | if (!S_ISREG(sbuf.st_mode)) 383 | {//不是一个普通文件 384 | CHEN_LOG(WARN,"failed to open file"); 385 | return; 386 | } 387 | int bytes_to_send = sbuf.st_size; // 文件大小 388 | close(fd); 389 | FILE *fp = fopen(localname.c_str(),"rb"); //以二进制读取 390 | if(fp == NULL) 391 | CHEN_LOG(ERROR,"open file %s error",localname.c_str()); 392 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 393 | info_ptr->isIdle = false; 394 | info_ptr->fp = fp; 395 | info_ptr->sendFilename = localname; 396 | sendfileMaps[localname].push_back(conn); 397 | conn->setWriteCompleteCallback(boost::bind(&SyncServer::onWriteComplete,this,conn)); 398 | //先发送fileInfo信息 399 | filesync::FileInfo msg; 400 | msg.set_size(bytes_to_send); 401 | msg.set_filename(localname.substr(rootDir.size())); 402 | conn->send(Codec::enCode(msg)); 403 | CHEN_LOG(INFO,"SEND FILEINFO :%s",localname.c_str()); 404 | } 405 | 406 | /** 407 | * @brief onWriteComplete fileInfo信息发送完或一块文件发送完执行此函数, 408 | * 此函数仅在sendfileWithproto函数中被注册,文件发送完后执行下一个发送任务 409 | * @param conn 用此conn发送 410 | */ 411 | void SyncServer::onWriteComplete(const muduo::net::TcpConnectionPtr &conn) 412 | { 413 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 414 | FILE* fp = info_ptr->fp; 415 | size_t nread = -1; 416 | char buf[64*1024]; //一次发64k 417 | if(!info_ptr->isRemoved_sending) 418 | nread = ::fread(buf, 1, sizeof buf, fp); 419 | if(nread <=0 || info_ptr->isRemoved_sending) 420 | { 421 | CHEN_LOG(INFO,"SEND FILE completed:%s",info_ptr->sendFilename.c_str()); 422 | if(info_ptr->isRemoved_sending) 423 | {//说明该文件已被删除,告知客户端已发送的大小 424 | // sysutil::send_SyncInfo(userMaps[info_ptr->username][0],3, 425 | // info_ptr->sendFilename.substr(rootDir.size()),"",info_ptr->sendSize); 426 | char buf[10] = {0}; 427 | sprintf(buf,"%d",info_ptr->sendSize); 428 | conn->sendOOB(buf,sizeof(buf)); 429 | CHEN_LOG(INFO,"SEND SIZE :%d",info_ptr->sendSize); 430 | } 431 | auto it_map = sendfileMaps.find(info_ptr->username); 432 | if(it_map!=sendfileMaps.end()) 433 | {//从sendfileMaps删除此次发送 434 | for(auto it_vec = it_map->second.begin();it_vec!=it_map->second.end();) 435 | { 436 | if(it_vec->get() == conn.get()) 437 | it_map->second.erase(it_vec); 438 | else 439 | ++it_vec; 440 | } 441 | } 442 | conn->setWriteCompleteCallback(NULL); 443 | info_ptr->fp = NULL; 444 | info_ptr->isIdle = true; 445 | info_ptr->isRemoved_sending = false; 446 | info_ptr->sendSize = 0; 447 | info_ptr->sendFilename.clear(); 448 | doNextSend(conn); //用此连接执行下一个发送任务 449 | } 450 | else if (nread > 0) 451 | { 452 | conn->send(buf, static_cast(nread)); 453 | info_ptr->sendSize += nread; 454 | } 455 | 456 | } 457 | /** 458 | * @brief SyncServer::getIdleConn 获取该客户端的空闲文件传输连接 459 | * @param username 该客户端的username 460 | * @return 461 | */ 462 | muduo::net::TcpConnectionPtr SyncServer::getIdleConn(string username) 463 | { 464 | userMaps_mutex.lock(); 465 | Con_Vec conVec = userMaps[username]; 466 | userMaps_mutex.unlock(); 467 | for(auto it:conVec) 468 | { 469 | Info_ConnPtr info_ptr = boost::any_cast(it->getContext()); 470 | if(info_ptr->type == ConType::CONTROL) 471 | continue; 472 | if(info_ptr->isIdle) 473 | return it; 474 | } 475 | return nullptr; 476 | } 477 | /** 478 | * @brief SyncServer::doNextSend 从发送队列取出任务执行 479 | * @param conn 480 | */ 481 | void SyncServer::doNextSend(const muduo::net::TcpConnectionPtr &conn) 482 | { 483 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 484 | sendListMaps_mutex.lock(); 485 | auto it = sendListMaps.find(info_ptr->username); 486 | if(it != sendListMaps.end()) 487 | { 488 | if(!it->second.empty()) 489 | { 490 | SendTask task = it->second.front().second; 491 | it->second.pop_front(); 492 | sendListMaps_mutex.unlock(); 493 | task(conn); 494 | } 495 | else 496 | sendListMaps_mutex.unlock(); 497 | } 498 | else 499 | { 500 | sendListMaps_mutex.unlock(); 501 | CHEN_LOG(ERROR,"can't find send queue"); 502 | } 503 | sendListMaps_mutex.unlock(); 504 | } 505 | 506 | void SyncServer::syncToClient(const muduo::net::TcpConnectionPtr &conn,string dir, 507 | vector &files) 508 | { 509 | DIR *odir = NULL; 510 | if((odir = opendir(dir.c_str())) == NULL) 511 | CHEN_LOG(ERROR,"open dir %s error",dir.c_str()); 512 | struct dirent *dent; 513 | while((dent = readdir(odir)) != NULL) 514 | { 515 | if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) 516 | continue; 517 | string subdir = string(dir) + dent->d_name; 518 | string remote_subdir = subdir.substr(rootDir.size()); 519 | bool isFound = false; 520 | for(auto it:files) 521 | { 522 | if(it == subdir) 523 | { 524 | isFound = true; 525 | break; 526 | } 527 | } 528 | if(isFound) 529 | continue; 530 | if(dent->d_type == DT_DIR) 531 | {//文件夹 532 | sysutil::send_SyncInfo(conn,0,remote_subdir); 533 | syncToClient(conn,(subdir + "/").c_str(),files); 534 | } 535 | else 536 | { 537 | Info_ConnPtr info_ptr = boost::any_cast(conn->getContext()); 538 | string username = info_ptr->username; 539 | muduo::net::TcpConnectionPtr idleConn = getIdleConn(username); 540 | if(idleConn == nullptr) 541 | {//加入发送队列 542 | muduo::MutexLockGuard mutexLock(sendListMaps_mutex); 543 | sendListMaps[username].push_back( 544 | {subdir,std::bind(&SyncServer::sendfileWithproto,this, 545 | std::placeholders::_1,subdir) 546 | }); 547 | } 548 | else 549 | sendfileWithproto(idleConn,subdir); 550 | } 551 | } 552 | } 553 | /** 554 | * @brief SyncServer::initMd5 初始化md5Maps 555 | */ 556 | void SyncServer::initMd5(string dir) 557 | { 558 | DIR *odir = NULL; 559 | if((odir = opendir(dir.c_str())) == NULL) 560 | CHEN_LOG(ERROR,"open dir %s error",dir.c_str()); 561 | struct dirent *dent; 562 | while((dent = readdir(odir)) != NULL) 563 | { 564 | if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) 565 | continue; 566 | string subdir = string(dir) + dent->d_name; 567 | if(dent->d_type == DT_DIR) 568 | {//文件夹 569 | initMd5(subdir + "/"); 570 | } 571 | else 572 | { 573 | string md5 = sysutil::getFileMd5(subdir); 574 | md5Maps.insert(make_pair(subdir,md5)); 575 | } 576 | } 577 | } 578 | 579 | -------------------------------------------------------------------------------- /syncserver.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNCSERVER_H 2 | #define SYNCSERVER_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "parseconfig.h" 14 | #include "codec.h" 15 | #include "protobuf/filesync.pb.h" 16 | 17 | //TcpConnectionPtr的context存放着此conn的类型 18 | enum ConType { CONTROL=1,DATA }; 19 | //TcpConnection的context存放的结构体 20 | struct Info_Conn{ 21 | ConType type; 22 | std::string username; 23 | bool isIdle = true; //是否可发送 24 | bool isRecving = false; //是否正在接收文件 25 | bool isRemoved_receving = false; //接收到一半被删除 26 | bool isRemoved_sending = false; //发送到一半被删除 27 | int totalSize = 0; //要接收文件的大小 28 | int remainSize = 0; //还未接收的大小 29 | int sendSize = 0; //已发送的文件大小 30 | std::string sendFilename; 31 | std::string receiveFilename; //正在接收的文件名 32 | std::string md5; //要接收的文件的md5 33 | FILE *fp; //要发送的文件的fp 34 | }; 35 | typedef std::shared_ptr Info_ConnPtr; 36 | 37 | //相应protobuf消息的回调函数 38 | typedef std::shared_ptr SignInPtr; 39 | typedef std::shared_ptr InitPtr; 40 | typedef std::shared_ptr SyncInfoPtr; 41 | typedef std::shared_ptr FileInfoPtr; 42 | 43 | class SyncServer 44 | { 45 | public: 46 | SyncServer(muduo::net::EventLoop *loop, int port); 47 | void start() { server_.start(); } 48 | private: 49 | static const int KHeaderLen = 4; //包的长度信息为4字节 50 | 51 | muduo::net::InetAddress serverAddr; 52 | muduo::net::TcpServer server_; 53 | ParseConfig *pc; 54 | Codec codec; 55 | std::string rootDir; //要同步的文件夹 56 | //存放此用户对应的TcpConnection,这样可以方便查看此用户连接的次数,以决定此conn的类型 57 | //在此用户掉线时,也能方便关掉所有的conn 58 | typedef std::vector Con_Vec; 59 | std::unordered_map userMaps; 60 | muduo::MutexLock userMaps_mutex; 61 | //正在发送的文件和conn数组 62 | std::unordered_map sendfileMaps; 63 | //文件名和md5的map 64 | std::unordered_map md5Maps; 65 | muduo::MutexLock md5Maps_mutex; 66 | 67 | typedef std::function SendTask; 68 | //发送文件的任务列表pair第一个元素为文件名 69 | typedef std::list> TaskList; 70 | //每个用户一个任务列表 71 | std::unordered_map sendListMaps; 72 | muduo::MutexLock sendListMaps_mutex; 73 | 74 | //连接到来的处理函数 75 | void onConnection(const muduo::net::TcpConnectionPtr &conn); 76 | //接收原始包的处理函数 77 | void onMessage(const muduo::net::TcpConnectionPtr &conn, 78 | muduo::net::Buffer *buf,muduo::Timestamp receiveTime); 79 | //连接断开的处理函数 80 | void onShutDown(const muduo::net::TcpConnectionPtr &conn); 81 | 82 | //接收到相应protobuf的处理函数 83 | void onSignIn(const muduo::net::TcpConnectionPtr &conn, const SignInPtr &message); 84 | void onInit(const muduo::net::TcpConnectionPtr &conn, const InitPtr &message); 85 | void onSyncInfo(const muduo::net::TcpConnectionPtr &conn, const SyncInfoPtr &message); 86 | void onSendFile(muduo::net::TcpConnectionPtr &conn,MessagePtr message); 87 | void onFileInfo(const muduo::net::TcpConnectionPtr &conn, const FileInfoPtr &message); 88 | 89 | void handleRemove_sending(std::string localname); 90 | 91 | //找出客户端不存在的文件并发送给客户端 92 | void recvFile(const muduo::net::TcpConnectionPtr &conn,Info_ConnPtr &info_ptr); 93 | void sendfileWithproto(const muduo::net::TcpConnectionPtr &conn, std::string &localname); 94 | void onWriteComplete(const muduo::net::TcpConnectionPtr &conn); 95 | muduo::net::TcpConnectionPtr getIdleConn(std::string ip); //获取该客户端的空闲文件传输连接 96 | void doNextSend(const muduo::net::TcpConnectionPtr &conn);//执行下一个发送任务 97 | void syncToClient(const muduo::net::TcpConnectionPtr &conn, std::string dir, std::vector &files); 98 | void initMd5(std::string dir); 99 | }; 100 | 101 | #endif // SYNCSERVER_H 102 | -------------------------------------------------------------------------------- /sysutil.cpp: -------------------------------------------------------------------------------- 1 | #include "sysutil.h" 2 | #include 3 | #include 4 | #include "codec.h" 5 | #include "protobuf/filesync.pb.h" 6 | 7 | using namespace std; 8 | namespace sysutil{ 9 | 10 | /** 11 | * writen - 发送固定字节数 12 | * @fd: 文件描述符 13 | * @buf: 发送缓冲区 14 | * @count: 要读取的字节数 15 | * 成功返回count,失败返回-1 16 | */ 17 | ssize_t writen(int fd, const void *buf, size_t count) 18 | { 19 | size_t nleft = count; 20 | ssize_t nwritten; 21 | char *bufp = (char*)buf; 22 | 23 | while (nleft > 0) 24 | { 25 | if ((nwritten = write(fd, bufp, nleft)) < 0) 26 | { 27 | if (errno == EINTR) 28 | continue; 29 | return -1; 30 | } 31 | else if (nwritten == 0) 32 | continue; 33 | 34 | bufp += nwritten; 35 | nleft -= nwritten; 36 | } 37 | 38 | return count; 39 | } 40 | //从应用层缓冲区读取文件数据,append到文件后面 41 | void fileRecvfromBuf(const char *filename,const char *buf,int size) 42 | { 43 | int fd = open(filename, O_CREAT | O_WRONLY, 0666); 44 | if (fd == -1) 45 | { 46 | CHEN_LOG(ERROR,"Could not create file %s",filename); 47 | return; 48 | } 49 | lseek(fd,0,SEEK_END); 50 | if(write(fd,buf,size) < 0) 51 | CHEN_LOG(ERROR,"write file %s to %d error",filename,fd); 52 | close(fd); 53 | } 54 | 55 | /** 56 | * @brief send_SyncInfo 发送SyncInfo信息,线程安全 57 | * @param conn 58 | * @param id 0是创建文件夹,1是create文件,2是modify,3是删除,4是重命名 59 | * @param filename 60 | * @param newname 新文件名,发送重命名信息时才用 61 | * @param removedSize 删除正在发送的文件时,已发送的大小 62 | */ 63 | void send_SyncInfo(const muduo::net::TcpConnectionPtr &conn, int id, 64 | string filename, string newname,int removedSize) 65 | { 66 | filesync::SyncInfo msg; 67 | msg.set_id(id); 68 | msg.set_filename(filename); 69 | msg.set_size(removedSize); 70 | if(4 == id) //重命名 71 | msg.set_newfilename(newname); 72 | string send = Codec::enCode(msg); 73 | conn->send(send); 74 | } 75 | 76 | /** 77 | * @brief getFileMd5 利用qt库获取md5,支持大文件 78 | * @param filePath 文件名 79 | * @return 80 | */ 81 | string getFileMd5(string filePath) 82 | { 83 | QFile localFile(QString::fromStdString(filePath)); 84 | 85 | if (!localFile.open(QFile::ReadOnly)) 86 | { 87 | qDebug() << "file open error."; 88 | return 0; 89 | } 90 | 91 | QCryptographicHash ch(QCryptographicHash::Md5); 92 | 93 | quint64 totalBytes = 0; 94 | quint64 bytesWritten = 0; 95 | quint64 bytesToWrite = 0; 96 | quint64 loadSize = 1024 * 4; 97 | QByteArray buf; 98 | 99 | totalBytes = localFile.size(); 100 | bytesToWrite = totalBytes; 101 | 102 | while (1) 103 | { 104 | if(bytesToWrite > 0) 105 | { 106 | buf = localFile.read(qMin(bytesToWrite, loadSize)); 107 | ch.addData(buf); 108 | bytesWritten += buf.length(); 109 | bytesToWrite -= buf.length(); 110 | buf.resize(0); 111 | } 112 | else 113 | { 114 | break; 115 | } 116 | 117 | if(bytesWritten == totalBytes) 118 | { 119 | break; 120 | } 121 | } 122 | 123 | localFile.close(); 124 | QString md5 = ch.result().toHex(); 125 | return md5.toStdString(); 126 | } 127 | //获取字符串的md5 128 | string getStringMd5(char *buffer) 129 | { 130 | QCryptographicHash ch(QCryptographicHash::Md5); 131 | QByteArray buf(buffer); 132 | ch.addData(buf); 133 | QString md5 = ch.result().toHex(); 134 | return md5.toStdString(); 135 | } 136 | 137 | 138 | unsigned int adler32(char * data, int len) 139 | /* where data is the location of the data in physical memory and len is the length of the data in bytes */ 140 | { 141 | unsigned int a = 1, b = 0; 142 | int index; 143 | 144 | /* Process each byte of the data in order */ 145 | for (index = 0; index < len; ++index) 146 | { 147 | a = a + data[index]; 148 | b = b + a ; 149 | } 150 | return (b * 65536) + a; 151 | } 152 | unsigned int adler32_rolling_checksum(unsigned int csum, int len, char c1, char c2) 153 | { 154 | unsigned int s1, s2; 155 | s1 = (csum & 0xffff); 156 | s2 = (csum >> 16); 157 | s1 = (s1- c1) + c2; 158 | s2 = s2- (len * c1 - s1)-1; 159 | return (s2 * 65536) + s1; 160 | } 161 | 162 | 163 | } 164 | -------------------------------------------------------------------------------- /sysutil.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSUTIL_H 2 | #define SYSUTIL_H 3 | 4 | #include "common.h" 5 | #include "syncserver.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | /*系统工具*/ 13 | namespace sysutil{ 14 | ssize_t writen(int fd, const void *buf, size_t count); 15 | //从应用层缓冲区读取文件数据,append到文件后面 16 | void fileRecvfromBuf(const char *filename, const char *buf, int size); 17 | 18 | //先发送fileInfo信息再发送文件内容 19 | void sendfileWithproto(const muduo::net::TcpConnectionPtr &conn,Info_ConnPtr &info_ptr, 20 | const char* localname,const char *remotename); 21 | //发送syncInfo信息 22 | void send_SyncInfo(const muduo::net::TcpConnectionPtr &conn, int id, std::string filename, 23 | std::string newname = "", int removedSize=-1); 24 | //同步整个文件夹 25 | void sync_Dir(int socketfd, std::string root, std::string dir); 26 | //利用qt库获取md5,支持大文件 27 | std::string getFileMd5(std::string filePath); 28 | std::string getStringMd5(char *buffer); 29 | 30 | unsigned int adler32(char * data, int len); 31 | unsigned int adler32_rolling_checksum(unsigned int csum, int len, char c1, char c2); 32 | } 33 | #endif // SYSUTIL_H 34 | -------------------------------------------------------------------------------- /test/echo.h: -------------------------------------------------------------------------------- 1 | #ifndef MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H 2 | #define MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H 3 | 4 | #include 5 | 6 | // RFC 862 7 | class EchoServer 8 | { 9 | public: 10 | EchoServer(muduo::net::EventLoop* loop, 11 | const muduo::net::InetAddress& listenAddr); 12 | 13 | void start(); // calls server_.start(); 14 | 15 | private: 16 | void onConnection(const muduo::net::TcpConnectionPtr& conn); 17 | 18 | void onMessage(const muduo::net::TcpConnectionPtr& conn, 19 | muduo::net::Buffer* buf, 20 | muduo::Timestamp time); 21 | 22 | muduo::net::TcpServer server_; 23 | }; 24 | 25 | #endif // MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H 26 | -------------------------------------------------------------------------------- /test/filesendtest.cpp: -------------------------------------------------------------------------------- 1 | //#include "../socket.h" 2 | //#include "../sysutil.h" 3 | 4 | //using namespace std; 5 | //using namespace sysutil; 6 | 7 | //int main() 8 | //{ 9 | // TcpSocket socket; 10 | // socket.bind(8888); 11 | // socket.listen(); 12 | // int connect_fd = socket.accept(); 13 | // fileSend(connect_fd,"hehe"); 14 | // close(connect_fd); 15 | // return 0; 16 | //} 17 | -------------------------------------------------------------------------------- /test/muduo_test.cpp: -------------------------------------------------------------------------------- 1 | //#include "../syncserver.h" 2 | 3 | //int main() 4 | //{ 5 | // muduo::net::EventLoop loop; 6 | // SyncServer server(&loop,8888); 7 | // server.start(); 8 | // loop.loop(); 9 | // return 0; 10 | //} 11 | -------------------------------------------------------------------------------- /test/oobServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../common.h" 12 | 13 | /* 服务器要监听的本地端口 */ 14 | #define MYPORT 4000 15 | /* 能够同时接受多少没有 accept 的连接 */ 16 | #define BACKLOG 10 17 | int new_fd = -1;// 全局变量 连接套接字 主函数和SIGURG信号处理函数中均会调用 18 | void sig_urg(int signo); 19 | 20 | int main() 21 | { 22 | /* 在 sock_fd 上进行监听,new_fd 接受新的连接 */ 23 | int sockfd; 24 | /* 自己的地址信息 */ 25 | struct sockaddr_in my_addr; 26 | /* 连接者的地址信息*/ 27 | struct sockaddr_in their_addr; 28 | int sin_size; 29 | int n ; 30 | char buff[100] ; 31 | /* 用于存储以前系统缺省的 SIGURL 处理器的变量 */ 32 | sighandler_t old_sig_urg_handle ; 33 | /* 这里就是我们一直强调的错误检查.如果调用 socket() 出错,则返回 */ 34 | 35 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 36 | {/* 输出错误提示并退出 */ 37 | perror("socket"); 38 | exit(1); 39 | } 40 | /* 主机字节顺序 */ 41 | my_addr.sin_family = AF_INET; 42 | /* 网络字节顺序,短整型 */ 43 | my_addr.sin_port = htons(MYPORT); 44 | /* 将运行程序机器的 IP 填充入 s_addr */ 45 | my_addr.sin_addr.s_addr = INADDR_ANY; 46 | /* 将此结构的其余空间清零 */ 47 | bzero(&(my_addr.sin_zero), 8); 48 | /* 这里是我们一直强调的错误检查!! */ 49 | if (bind(sockfd, (struct sockaddr *)&my_addr,sizeof(struct sockaddr)) == -1) 50 | { 51 | /* 如果调用 bind()失败,则给出错误提示,退出 */ 52 | perror("bind"); 53 | exit(1); 54 | } 55 | /* 这里是我们一直强调的错误检查!! */ 56 | if (listen(sockfd, BACKLOG) == -1) 57 | { 58 | /* 如果调用 listen 失败,则给出错误提示,退出 */ 59 | perror("listen"); 60 | exit(1); 61 | } 62 | 63 | 64 | /* 设置 SIGURG 的处理函数 sig_urg */ 65 | old_sig_urg_handle = signal(SIGURG, sig_urg); 66 | /* 将我们的进程创建为套接口的拥有者 */ //wrong;非监听套接字 67 | /*if(fcntl(sockfd, F_SETOWN, getpid())==-1) 68 | { 69 | perror("fcntl"); 70 | exit(1); 71 | }*/ 72 | 73 | 74 | while(1) 75 | { 76 | /* 这里是主 accept()循环 */ 77 | sin_size = sizeof(struct sockaddr_in); 78 | 79 | /* 这里是我们一直强调的错误检查!! */ 80 | if ((new_fd = accept(sockfd, (struct sockaddr *)NULL, NULL)) == -1) 81 | { 82 | /* 如果调用 accept()出现错误,则给出错误提示,进入下一个循环 */ 83 | perror("accept"); 84 | continue; 85 | } 86 | //printf("in main, new_fd = %d\n",new_fd); 87 | fcntl(new_fd,F_SETOWN,getpid());//将我们的进程设置为(连接套接字)的拥有者 88 | 89 | /* 服务器给出出现连接的信息 */ 90 | printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); 91 | /* 这里将建立一个子进程来和刚刚建立的套接字进行通讯 */ 92 | //if (!fork()) 93 | if (1) 94 | { 95 | while(1) 96 | { 97 | if((n=recv(new_fd,buff,sizeof(buff)-1,0)) == 0) 98 | { 99 | printf("received EOF\n"); 100 | break; 101 | } 102 | buff[n] ='\0'; 103 | printf("Recv %d bytes: %s\n", n, buff); 104 | } 105 | } 106 | /* 关闭 new_fd 代表的这个套接字连接 */ 107 | close(new_fd); 108 | } 109 | /* 等待所有的子进程都退出 */ 110 | while(waitpid(-1,NULL,WNOHANG) > 0); 111 | /* 恢复系统以前对 SIGURG 的处理器 */ 112 | signal(SIGURG, old_sig_urg_handle); 113 | } 114 | 115 | void sig_urg(int signo) 116 | { 117 | int n; 118 | char buff[100]; 119 | printf("SIGURG received\n"); 120 | //printf("in sig_urg(),new_fd = %d\n",new_fd); 121 | //while((n = recv(new_fd,buff,sizeof(buff)-1,MSG_OOB)) == -1); 122 | n = recv(new_fd,buff,sizeof(buff)-1,MSG_OOB); 123 | if(n>0) 124 | { 125 | buff[n]='\0'; 126 | printf("recv %d OOB byte: %s\n",n,buff); 127 | } 128 | else 129 | { 130 | perror("recv"); 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /test/parsetest.cpp: -------------------------------------------------------------------------------- 1 | //#include "parseconfig.h" 2 | //#include 3 | //#include 4 | //using namespace std; 5 | 6 | //int main() 7 | //{ 8 | // ParseConfig *pc = ParseConfig::getInstance(); 9 | // pc->loadfile(); 10 | // cout<getSyncRoot()<checkUser("asd","123456")<checkUser("qwe","123456")< 5 | //#include 6 | //#include 7 | 8 | //using namespace std; 9 | //using namespace sysutil; 10 | //using namespace google::protobuf; 11 | 12 | //inline int32_t asInt32(const char* buf) 13 | //{ 14 | // int32_t be32 = 0; 15 | // ::memcpy(&be32, buf, sizeof(be32)); 16 | // return ::ntohl(be32); 17 | //} 18 | //Message* createMessage(const std::string& typeName) 19 | //{ 20 | // Message* message = NULL; 21 | // const Descriptor* descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(typeName); 22 | // if (descriptor) 23 | // { 24 | // const Message* prototype = MessageFactory::generated_factory()->GetPrototype(descriptor); 25 | // if (prototype) 26 | // { 27 | // message = prototype->New(); 28 | // } 29 | // } 30 | // return message; 31 | //} 32 | 33 | //int main() 34 | //{ 35 | // TcpSocket socket; 36 | // socket.bind(8888); 37 | // socket.listen(); 38 | // int connect_fd = socket.accept(); 39 | // char buf[10000]; 40 | // readn(connect_fd,buf,4); 41 | // int size = atoi(buf); 42 | // memset(buf,0,sizeof(buf)); 43 | // readn(connect_fd,buf,size); 44 | // int namelen = asInt32(buf); 45 | // string typeName(&buf[4],namelen); 46 | // cout< 4 | //#include 5 | //using namespace std; 6 | //#define Block_Size 2 7 | 8 | //list dataList; 9 | //char* holeData = (char*)malloc(sizeof(char)*(Block_Size*1024)); //1MB 10 | 11 | //void calSrcFile(string filename) 12 | //{ 13 | // FILE *fp = fopen(filename.c_str(),"rb"); 14 | // /*获取需要计算的块数,并分块计算,输出到文件*/ 15 | // fseek(fp, 0, SEEK_END);//获取文件尾 16 | // int end = ftell(fp); 17 | // int size = end / Block_Size; 18 | // rewind(fp);//重置文件指针 19 | // char* buff = (char*)malloc(sizeof(char)*(Block_Size+1 )); 20 | // for(int i=0;i holeInfoList) 34 | //{ 35 | // FILE *fp = fopen(filename.c_str(),"rb"); 36 | // int len = 0; 37 | // char *tmp = holeData; 38 | // for(auto it:holeInfoList) 39 | // { 40 | // fseek(fp,it->offset,SEEK_SET); 41 | // fread(tmp,sizeof(char),it->len,fp); 42 | // tmp += it->len; 43 | // len += it->len; 44 | // } 45 | // fseek(fp, 0, SEEK_END);//获取文件尾 46 | // int end = ftell(fp); 47 | // int num = end / Block_Size; 48 | // int size = end % Block_Size; 49 | // fseek(fp,num*Block_Size,SEEK_SET); 50 | // fread(tmp,sizeof(char),size,fp); 51 | // return len+size; 52 | //} 53 | 54 | //int main() 55 | //{ 56 | // string filename("/home/chen/Desktop/a.cpp"); 57 | // string t_filename("/home/chen/Desktop/hoho.cpp"); 58 | // calSrcFile(filename); 59 | // Rsync rsync(t_filename); 60 | // for(auto it:dataList) 61 | // rsync.addHashItem(it->adler32,it); 62 | // rsync.calRsync(); 63 | // memset(holeData,0,Block_Size*1024); 64 | // int len = sendData(filename,rsync.getHoleList()); 65 | // rsync.reconstruct(holeData,len,"/home/chen/Desktop/hohohoh.cpp"); 66 | //} 67 | -------------------------------------------------------------------------------- /test/socketTest.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | //#include "../socket.h" 3 | //using namespace std; 4 | 5 | //int main() 6 | //{ 7 | // TcpSocket socket; 8 | // socket.bind(8888); 9 | // socket.listen(); 10 | // int connect_fd = socket.accept(); 11 | // char buf[10000]; 12 | // int n = recv(connect_fd,buf,10000,0); 13 | // cout<