├── ChatRoom.exe ├── README.md ├── chatRoom ├── ChatRoom.ico ├── ChatRoom.pro ├── ChatRoom.pro.user ├── ChatRoom.pro.user.0360db3 ├── ChatRoom.pro.user.383c2b9 ├── ChatRoom.pro.user.b25dcfa ├── ChatRoom.pro.user.f898218 ├── addfriends.cpp ├── addfriends.h ├── chatroom.cpp ├── chatroom.h ├── command.h ├── drawer.cpp ├── drawer.h ├── friendslist.cpp ├── friendslist.h ├── images.qrc ├── images │ ├── 1.png │ ├── ChatRoom.jpg │ ├── Linux.jpg │ ├── boss.png │ ├── jj.png │ ├── jj2.png │ ├── l.png │ ├── liu.png │ ├── m.png │ ├── m2.png │ ├── qq.png │ ├── w.png │ ├── w2.png │ ├── z.png │ └── zz.png ├── information.h ├── main.cpp ├── onlinestate.cpp ├── onlinestate.h ├── sign.cpp ├── sign.h ├── tcpclient.cpp ├── tcpclient.h ├── widget.cpp ├── widget.h └── widget.ui ├── server_mysql ├── Makefile ├── MyReactor.cpp ├── MyReactor.h ├── command.h ├── main └── main.cpp └── spdlog-1.x.zip /ChatRoom.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/ChatRoom.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TCP-ChatRoom 2 | 基于云服务器的TCP网络聊天室【客户端Qt5.6开发、后台服务器多进程实现、Mysql数据库管理用户信息】 3 | - **客户端** 4 | 5 | win10下的客户端 6 | 7 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022213925511.png) 8 | 9 | Ubuntu下客户端 10 | 11 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022214033201.png) 12 | 13 | 聊天室 14 | 15 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022214506319.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzY1ODI1,size_16,color_FFFFFF,t_70) 16 | 17 | 接收到好友请求 18 | 19 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022214824916.png) 20 | 21 | 是否同意?拒绝后,发送请求的一方会受到拒绝信息。 22 | 23 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022214850469.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzY1ODI1,size_16,color_FFFFFF,t_70) 24 | 25 | 更换头像,实时更新,将头像信息回传到服务器。 26 | 27 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022215305872.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzY1ODI1,size_16,color_FFFFFF,t_70) 28 | 29 | 实时更新好友头像,和状态信息 30 | 31 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022215650713.png) 32 | 33 | - **服务器端** 34 | 35 | 服务器后台记录在这里插入图片描述 36 | 37 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022214118311.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzY1ODI1,size_16,color_FFFFFF,t_70) 38 | 39 | 服务器数据库 40 | 41 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191022214157655.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzY1ODI1,size_16,color_FFFFFF,t_70) 42 | 43 | - **注意** 44 | 45 | 日志库spdlog需要把其文件夹中的include/spdlog 文件夹放到Linux系统/usr/include 目录下 46 | 47 | 数据库相关函数需要mysql.h头文件,需要Linux系统安装mysql软件 48 | 49 | sudo apt-get install mysql-server 50 | 51 | sudo apt-get install libmysqlclient-dev[开发包,不安装会提示找不到mysql.h头文件] 52 | 53 | 我用的数据库名称叫做ChatRoom,若你的mysql中没有这一数据库,会提示连接数据库失败 54 | 55 | 保存用户信息的表的结构,在上面给出的图片可以看到 56 | 57 | 服务器IP为腾讯云服务器IP,这样可以保证公网下的用户都能连接上,测试时要修改为你的本地IP,客户端,服务器端都要改 58 | -------------------------------------------------------------------------------- /chatRoom/ChatRoom.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/ChatRoom.ico -------------------------------------------------------------------------------- /chatRoom/ChatRoom.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2018-07-13T15:04:31 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | QT += network 9 | 10 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 11 | 12 | TARGET = ChatRoom 13 | TEMPLATE = app 14 | 15 | # The following define makes your compiler emit warnings if you use 16 | # any feature of Qt which as been marked as deprecated (the exact warnings 17 | # depend on your compiler). Please consult the documentation of the 18 | # deprecated API in order to know how to port your code away from it. 19 | DEFINES += QT_DEPRECATED_WARNINGS 20 | 21 | # You can also make your code fail to compile if you use deprecated APIs. 22 | # In order to do so, uncomment the following line. 23 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 24 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 25 | 26 | 27 | SOURCES += main.cpp\ 28 | sign.cpp \ 29 | drawer.cpp \ 30 | tcpclient.cpp \ 31 | addfriends.cpp \ 32 | friendslist.cpp \ 33 | onlinestate.cpp 34 | 35 | HEADERS += \ 36 | sign.h \ 37 | command.h \ 38 | drawer.h \ 39 | tcpclient.h \ 40 | addfriends.h \ 41 | friendslist.h \ 42 | onlinestate.h 43 | 44 | FORMS += 45 | 46 | RESOURCES += \ 47 | images.qrc 48 | RC_ICONS = ChatRoom.ico 49 | -------------------------------------------------------------------------------- /chatRoom/ChatRoom.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {f8982184-467d-44fa-be12-d0f9d607f079} 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 | 0 45 | 8 46 | true 47 | 1 48 | true 49 | true 50 | true 51 | false 52 | 53 | 54 | 55 | ProjectExplorer.Project.PluginSettings 56 | 57 | 58 | 59 | ProjectExplorer.Project.Target.0 60 | 61 | Desktop Qt 5.6.0 MinGW 32bit 62 | Desktop Qt 5.6.0 MinGW 32bit 63 | qt.56.win32_mingw49_kit 64 | 1 65 | 0 66 | 0 67 | 68 | C:/Users/Realself/Desktop/SoftWareFiles/QtCreator/build-chatRoom-Desktop_Qt_5_6_0_MinGW_32bit-Debug 69 | 70 | 71 | true 72 | qmake 73 | 74 | QtProjectManager.QMakeBuildStep 75 | true 76 | 77 | false 78 | false 79 | false 80 | 81 | 82 | true 83 | Make 84 | 85 | Qt4ProjectManager.MakeStep 86 | 87 | false 88 | 89 | 90 | 91 | 2 92 | 构建 93 | 94 | ProjectExplorer.BuildSteps.Build 95 | 96 | 97 | 98 | true 99 | Make 100 | 101 | Qt4ProjectManager.MakeStep 102 | 103 | true 104 | clean 105 | 106 | 107 | 1 108 | 清理 109 | 110 | ProjectExplorer.BuildSteps.Clean 111 | 112 | 2 113 | false 114 | 115 | Debug 116 | 117 | Qt4ProjectManager.Qt4BuildConfiguration 118 | 2 119 | true 120 | 121 | 122 | C:/Users/Realself/Desktop/SoftWareFiles/QtCreator/build-chatRoom-Desktop_Qt_5_6_0_MinGW_32bit-Release 123 | 124 | 125 | true 126 | qmake 127 | 128 | QtProjectManager.QMakeBuildStep 129 | false 130 | 131 | false 132 | false 133 | false 134 | 135 | 136 | true 137 | Make 138 | 139 | Qt4ProjectManager.MakeStep 140 | 141 | false 142 | 143 | 144 | 145 | 2 146 | 构建 147 | 148 | ProjectExplorer.BuildSteps.Build 149 | 150 | 151 | 152 | true 153 | Make 154 | 155 | Qt4ProjectManager.MakeStep 156 | 157 | true 158 | clean 159 | 160 | 161 | 1 162 | 清理 163 | 164 | ProjectExplorer.BuildSteps.Clean 165 | 166 | 2 167 | false 168 | 169 | Release 170 | 171 | Qt4ProjectManager.Qt4BuildConfiguration 172 | 0 173 | true 174 | 175 | 176 | C:/Users/Realself/Downloads/chatRoom-master/daySix/build-ChatRoom-Desktop_Qt_5_6_0_MinGW_32bit-Profile 177 | 178 | 179 | true 180 | qmake 181 | 182 | QtProjectManager.QMakeBuildStep 183 | true 184 | 185 | false 186 | true 187 | false 188 | 189 | 190 | true 191 | Make 192 | 193 | Qt4ProjectManager.MakeStep 194 | 195 | false 196 | 197 | 198 | 199 | 2 200 | 构建 201 | 202 | ProjectExplorer.BuildSteps.Build 203 | 204 | 205 | 206 | true 207 | Make 208 | 209 | Qt4ProjectManager.MakeStep 210 | 211 | true 212 | clean 213 | 214 | 215 | 1 216 | 清理 217 | 218 | ProjectExplorer.BuildSteps.Clean 219 | 220 | 2 221 | false 222 | 223 | Profile 224 | 225 | Qt4ProjectManager.Qt4BuildConfiguration 226 | 0 227 | true 228 | 229 | 3 230 | 231 | 232 | 0 233 | 部署 234 | 235 | ProjectExplorer.BuildSteps.Deploy 236 | 237 | 1 238 | 在本地部署 239 | 240 | ProjectExplorer.DefaultDeployConfiguration 241 | 242 | 1 243 | 244 | 245 | false 246 | 1000 247 | 248 | true 249 | 250 | false 251 | false 252 | false 253 | false 254 | true 255 | 0.01 256 | 10 257 | true 258 | 1 259 | 25 260 | 261 | 1 262 | true 263 | false 264 | true 265 | valgrind 266 | 267 | 0 268 | 1 269 | 2 270 | 3 271 | 4 272 | 5 273 | 6 274 | 7 275 | 8 276 | 9 277 | 10 278 | 11 279 | 12 280 | 13 281 | 14 282 | 283 | 2 284 | 285 | ChatRoom 286 | ChatRoom2 287 | Qt4ProjectManager.Qt4RunConfiguration:C:/Users/Realself/Desktop/SoftWareFiles/QtCreator/chatRoom/ChatRoom.pro 288 | true 289 | 290 | ChatRoom.pro 291 | false 292 | false 293 | 294 | 3768 295 | false 296 | true 297 | false 298 | false 299 | true 300 | 301 | 1 302 | 303 | 304 | 305 | ProjectExplorer.Project.TargetCount 306 | 1 307 | 308 | 309 | ProjectExplorer.Project.Updater.FileVersion 310 | 18 311 | 312 | 313 | Version 314 | 18 315 | 316 | 317 | -------------------------------------------------------------------------------- /chatRoom/ChatRoom.pro.user.0360db3: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {0360db30-20c5-4c1d-9aaf-58d00c53f6cd} 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 | ProjectExplorer.Project.Target.0 61 | 62 | Desktop Qt 5.8.0 MinGW 32bit 63 | Desktop Qt 5.8.0 MinGW 32bit 64 | qt.58.win32_mingw53_kit 65 | 0 66 | 0 67 | 0 68 | 69 | D:/QT/build-ChatRoom-Desktop_Qt_5_8_0_MinGW_32bit-Debug 70 | 71 | 72 | true 73 | qmake 74 | 75 | QtProjectManager.QMakeBuildStep 76 | true 77 | 78 | false 79 | false 80 | false 81 | 82 | 83 | true 84 | Make 85 | 86 | Qt4ProjectManager.MakeStep 87 | 88 | false 89 | 90 | 91 | 92 | 2 93 | 构建 94 | 95 | ProjectExplorer.BuildSteps.Build 96 | 97 | 98 | 99 | true 100 | Make 101 | 102 | Qt4ProjectManager.MakeStep 103 | 104 | true 105 | clean 106 | 107 | 108 | 1 109 | 清理 110 | 111 | ProjectExplorer.BuildSteps.Clean 112 | 113 | 2 114 | false 115 | 116 | Debug 117 | 118 | Qt4ProjectManager.Qt4BuildConfiguration 119 | 2 120 | true 121 | 122 | 123 | D:/QT/build-ChatRoom-Desktop_Qt_5_8_0_MinGW_32bit-Release 124 | 125 | 126 | true 127 | qmake 128 | 129 | QtProjectManager.QMakeBuildStep 130 | false 131 | 132 | false 133 | false 134 | false 135 | 136 | 137 | true 138 | Make 139 | 140 | Qt4ProjectManager.MakeStep 141 | 142 | false 143 | 144 | 145 | 146 | 2 147 | 构建 148 | 149 | ProjectExplorer.BuildSteps.Build 150 | 151 | 152 | 153 | true 154 | Make 155 | 156 | Qt4ProjectManager.MakeStep 157 | 158 | true 159 | clean 160 | 161 | 162 | 1 163 | 清理 164 | 165 | ProjectExplorer.BuildSteps.Clean 166 | 167 | 2 168 | false 169 | 170 | Release 171 | 172 | Qt4ProjectManager.Qt4BuildConfiguration 173 | 0 174 | true 175 | 176 | 177 | D:/QT/build-ChatRoom-Desktop_Qt_5_8_0_MinGW_32bit-Profile 178 | 179 | 180 | true 181 | qmake 182 | 183 | QtProjectManager.QMakeBuildStep 184 | true 185 | 186 | false 187 | true 188 | false 189 | 190 | 191 | true 192 | Make 193 | 194 | Qt4ProjectManager.MakeStep 195 | 196 | false 197 | 198 | 199 | 200 | 2 201 | 构建 202 | 203 | ProjectExplorer.BuildSteps.Build 204 | 205 | 206 | 207 | true 208 | Make 209 | 210 | Qt4ProjectManager.MakeStep 211 | 212 | true 213 | clean 214 | 215 | 216 | 1 217 | 清理 218 | 219 | ProjectExplorer.BuildSteps.Clean 220 | 221 | 2 222 | false 223 | 224 | Profile 225 | 226 | Qt4ProjectManager.Qt4BuildConfiguration 227 | 0 228 | true 229 | 230 | 3 231 | 232 | 233 | 0 234 | 部署 235 | 236 | ProjectExplorer.BuildSteps.Deploy 237 | 238 | 1 239 | 在本地部署 240 | 241 | ProjectExplorer.DefaultDeployConfiguration 242 | 243 | 1 244 | 245 | 246 | false 247 | false 248 | 1000 249 | 250 | true 251 | 252 | false 253 | false 254 | false 255 | false 256 | true 257 | 0.01 258 | 10 259 | true 260 | 1 261 | 25 262 | 263 | 1 264 | true 265 | false 266 | true 267 | valgrind 268 | 269 | 0 270 | 1 271 | 2 272 | 3 273 | 4 274 | 5 275 | 6 276 | 7 277 | 8 278 | 9 279 | 10 280 | 11 281 | 12 282 | 13 283 | 14 284 | 285 | 2 286 | 287 | ChatRoom 288 | 289 | Qt4ProjectManager.Qt4RunConfiguration:D:/QT/ChatRoom/ChatRoom.pro 290 | true 291 | 292 | ChatRoom.pro 293 | false 294 | 295 | D:/QT/build-ChatRoom-Desktop_Qt_5_8_0_MinGW_32bit-Debug 296 | 3768 297 | false 298 | true 299 | false 300 | false 301 | true 302 | 303 | 1 304 | 305 | 306 | 307 | ProjectExplorer.Project.TargetCount 308 | 1 309 | 310 | 311 | ProjectExplorer.Project.Updater.FileVersion 312 | 18 313 | 314 | 315 | Version 316 | 18 317 | 318 | 319 | -------------------------------------------------------------------------------- /chatRoom/ChatRoom.pro.user.383c2b9: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {383c2b94-d5e2-4e15-b8e8-b6cb3f698278} 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 | 0 45 | 8 46 | true 47 | 1 48 | true 49 | true 50 | true 51 | false 52 | 53 | 54 | 55 | ProjectExplorer.Project.PluginSettings 56 | 57 | 58 | 59 | ProjectExplorer.Project.Target.0 60 | 61 | Desktop Qt 5.6.0 GCC 64bit 62 | Desktop Qt 5.6.0 GCC 64bit 63 | qt.56.gcc_64_kit 64 | 0 65 | 0 66 | 0 67 | 68 | /home/mtf/文档/LinuxNetwork/ChatRoom/daySeven 69 | 70 | 71 | true 72 | qmake 73 | 74 | QtProjectManager.QMakeBuildStep 75 | true 76 | 77 | false 78 | false 79 | false 80 | 81 | 82 | true 83 | Make 84 | 85 | Qt4ProjectManager.MakeStep 86 | 87 | -w 88 | -r 89 | 90 | false 91 | 92 | 93 | 94 | 2 95 | 构建 96 | 97 | ProjectExplorer.BuildSteps.Build 98 | 99 | 100 | 101 | true 102 | Make 103 | 104 | Qt4ProjectManager.MakeStep 105 | 106 | -w 107 | -r 108 | 109 | true 110 | clean 111 | 112 | 113 | 1 114 | 清理 115 | 116 | ProjectExplorer.BuildSteps.Clean 117 | 118 | 2 119 | false 120 | 121 | Debug 122 | 123 | Qt4ProjectManager.Qt4BuildConfiguration 124 | 2 125 | true 126 | 127 | 128 | /home/mtf/下载/chatRoom-master/daySix/build-ChatRoom-Desktop_Qt_5_6_0_GCC_64bit-Release 129 | 130 | 131 | true 132 | qmake 133 | 134 | QtProjectManager.QMakeBuildStep 135 | false 136 | 137 | false 138 | false 139 | false 140 | 141 | 142 | true 143 | Make 144 | 145 | Qt4ProjectManager.MakeStep 146 | 147 | -w 148 | -r 149 | 150 | false 151 | 152 | 153 | 154 | 2 155 | 构建 156 | 157 | ProjectExplorer.BuildSteps.Build 158 | 159 | 160 | 161 | true 162 | Make 163 | 164 | Qt4ProjectManager.MakeStep 165 | 166 | -w 167 | -r 168 | 169 | true 170 | clean 171 | 172 | 173 | 1 174 | 清理 175 | 176 | ProjectExplorer.BuildSteps.Clean 177 | 178 | 2 179 | false 180 | 181 | Release 182 | 183 | Qt4ProjectManager.Qt4BuildConfiguration 184 | 0 185 | true 186 | 187 | 188 | /home/mtf/下载/chatRoom-master/daySix/build-ChatRoom-Desktop_Qt_5_6_0_GCC_64bit-Profile 189 | 190 | 191 | true 192 | qmake 193 | 194 | QtProjectManager.QMakeBuildStep 195 | true 196 | 197 | false 198 | true 199 | false 200 | 201 | 202 | true 203 | Make 204 | 205 | Qt4ProjectManager.MakeStep 206 | 207 | -w 208 | -r 209 | 210 | false 211 | 212 | 213 | 214 | 2 215 | 构建 216 | 217 | ProjectExplorer.BuildSteps.Build 218 | 219 | 220 | 221 | true 222 | Make 223 | 224 | Qt4ProjectManager.MakeStep 225 | 226 | -w 227 | -r 228 | 229 | true 230 | clean 231 | 232 | 233 | 1 234 | 清理 235 | 236 | ProjectExplorer.BuildSteps.Clean 237 | 238 | 2 239 | false 240 | 241 | Profile 242 | 243 | Qt4ProjectManager.Qt4BuildConfiguration 244 | 0 245 | true 246 | 247 | 3 248 | 249 | 250 | 0 251 | 部署 252 | 253 | ProjectExplorer.BuildSteps.Deploy 254 | 255 | 1 256 | 在本地部署 257 | 258 | ProjectExplorer.DefaultDeployConfiguration 259 | 260 | 1 261 | 262 | 263 | false 264 | 1000 265 | 266 | true 267 | 268 | false 269 | false 270 | false 271 | false 272 | true 273 | 0.01 274 | 10 275 | true 276 | 1 277 | 25 278 | 279 | 1 280 | true 281 | false 282 | true 283 | valgrind 284 | 285 | 0 286 | 1 287 | 2 288 | 3 289 | 4 290 | 5 291 | 6 292 | 7 293 | 8 294 | 9 295 | 10 296 | 11 297 | 12 298 | 13 299 | 14 300 | 301 | 2 302 | 303 | ChatRoom 304 | 305 | Qt4ProjectManager.Qt4RunConfiguration:/home/mtf/文档/LinuxNetwork/ChatRoom/daySeven/chatRoom/ChatRoom.pro 306 | true 307 | 308 | ChatRoom.pro 309 | false 310 | false 311 | 312 | 3768 313 | false 314 | true 315 | false 316 | false 317 | true 318 | 319 | 1 320 | 321 | 322 | 323 | ProjectExplorer.Project.TargetCount 324 | 1 325 | 326 | 327 | ProjectExplorer.Project.Updater.FileVersion 328 | 18 329 | 330 | 331 | Version 332 | 18 333 | 334 | 335 | -------------------------------------------------------------------------------- /chatRoom/ChatRoom.pro.user.f898218: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {f8982184-467d-44fa-be12-d0f9d607f079} 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 | 0 45 | 8 46 | true 47 | 1 48 | true 49 | true 50 | true 51 | false 52 | 53 | 54 | 55 | ProjectExplorer.Project.PluginSettings 56 | 57 | 58 | 59 | ProjectExplorer.Project.Target.0 60 | 61 | Desktop Qt 5.6.0 MinGW 32bit 62 | Desktop Qt 5.6.0 MinGW 32bit 63 | qt.56.win32_mingw49_kit 64 | 0 65 | 0 66 | 0 67 | 68 | C:/Users/Realself/Downloads/chatRoom-master/daySix/build-ChatRoom-Desktop_Qt_5_6_0_MinGW_32bit-Debug 69 | 70 | 71 | true 72 | qmake 73 | 74 | QtProjectManager.QMakeBuildStep 75 | true 76 | 77 | false 78 | false 79 | false 80 | 81 | 82 | true 83 | Make 84 | 85 | Qt4ProjectManager.MakeStep 86 | 87 | false 88 | 89 | 90 | 91 | 2 92 | 构建 93 | 94 | ProjectExplorer.BuildSteps.Build 95 | 96 | 97 | 98 | true 99 | Make 100 | 101 | Qt4ProjectManager.MakeStep 102 | 103 | true 104 | clean 105 | 106 | 107 | 1 108 | 清理 109 | 110 | ProjectExplorer.BuildSteps.Clean 111 | 112 | 2 113 | false 114 | 115 | Debug 116 | 117 | Qt4ProjectManager.Qt4BuildConfiguration 118 | 2 119 | true 120 | 121 | 122 | C:/Users/Realself/Downloads/chatRoom-master/daySix/build-ChatRoom-Desktop_Qt_5_6_0_MinGW_32bit-Release 123 | 124 | 125 | true 126 | qmake 127 | 128 | QtProjectManager.QMakeBuildStep 129 | false 130 | 131 | false 132 | false 133 | false 134 | 135 | 136 | true 137 | Make 138 | 139 | Qt4ProjectManager.MakeStep 140 | 141 | false 142 | 143 | 144 | 145 | 2 146 | 构建 147 | 148 | ProjectExplorer.BuildSteps.Build 149 | 150 | 151 | 152 | true 153 | Make 154 | 155 | Qt4ProjectManager.MakeStep 156 | 157 | true 158 | clean 159 | 160 | 161 | 1 162 | 清理 163 | 164 | ProjectExplorer.BuildSteps.Clean 165 | 166 | 2 167 | false 168 | 169 | Release 170 | 171 | Qt4ProjectManager.Qt4BuildConfiguration 172 | 0 173 | true 174 | 175 | 176 | C:/Users/Realself/Downloads/chatRoom-master/daySix/build-ChatRoom-Desktop_Qt_5_6_0_MinGW_32bit-Profile 177 | 178 | 179 | true 180 | qmake 181 | 182 | QtProjectManager.QMakeBuildStep 183 | true 184 | 185 | false 186 | true 187 | false 188 | 189 | 190 | true 191 | Make 192 | 193 | Qt4ProjectManager.MakeStep 194 | 195 | false 196 | 197 | 198 | 199 | 2 200 | 构建 201 | 202 | ProjectExplorer.BuildSteps.Build 203 | 204 | 205 | 206 | true 207 | Make 208 | 209 | Qt4ProjectManager.MakeStep 210 | 211 | true 212 | clean 213 | 214 | 215 | 1 216 | 清理 217 | 218 | ProjectExplorer.BuildSteps.Clean 219 | 220 | 2 221 | false 222 | 223 | Profile 224 | 225 | Qt4ProjectManager.Qt4BuildConfiguration 226 | 0 227 | true 228 | 229 | 3 230 | 231 | 232 | 0 233 | 部署 234 | 235 | ProjectExplorer.BuildSteps.Deploy 236 | 237 | 1 238 | 在本地部署 239 | 240 | ProjectExplorer.DefaultDeployConfiguration 241 | 242 | 1 243 | 244 | 245 | false 246 | 1000 247 | 248 | true 249 | 250 | false 251 | false 252 | false 253 | false 254 | true 255 | 0.01 256 | 10 257 | true 258 | 1 259 | 25 260 | 261 | 1 262 | true 263 | false 264 | true 265 | valgrind 266 | 267 | 0 268 | 1 269 | 2 270 | 3 271 | 4 272 | 5 273 | 6 274 | 7 275 | 8 276 | 9 277 | 10 278 | 11 279 | 12 280 | 13 281 | 14 282 | 283 | 2 284 | 285 | ChatRoom 286 | 287 | Qt4ProjectManager.Qt4RunConfiguration:C:/Users/Realself/Downloads/chatRoom-master/daySix/ChatRoom/ChatRoom.pro 288 | true 289 | 290 | ChatRoom.pro 291 | false 292 | false 293 | 294 | 3768 295 | false 296 | true 297 | false 298 | false 299 | true 300 | 301 | 1 302 | 303 | 304 | 305 | ProjectExplorer.Project.TargetCount 306 | 1 307 | 308 | 309 | ProjectExplorer.Project.Updater.FileVersion 310 | 18 311 | 312 | 313 | Version 314 | 18 315 | 316 | 317 | -------------------------------------------------------------------------------- /chatRoom/addfriends.cpp: -------------------------------------------------------------------------------- 1 | #include "addfriends.h" 2 | #include "command.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | AddFriends::AddFriends(QWidget *parent) 10 | : QDialog(parent) 11 | { 12 | setWindowTitle(tr("添加好友")); 13 | this->setFixedSize(300,200); 14 | 15 | nameLabel = new QLabel(tr("Name:")); 16 | nameLineEdit = new QLineEdit(); 17 | enterBtn = new QPushButton("Enter"); 18 | 19 | tcpSocket = new QTcpSocket(this); 20 | 21 | mainLayout = new QGridLayout(this); 22 | mainLayout->addWidget(nameLabel, 0, 0); 23 | mainLayout->addWidget(nameLineEdit, 0, 1); 24 | mainLayout->addWidget(enterBtn, 1, 1); 25 | 26 | //连接服务器 27 | port = 12345; 28 | serverIP = new QHostAddress(); 29 | QString ip = SERVER_IP; 30 | serverIP->setAddress(ip); 31 | 32 | connect(enterBtn, SIGNAL(clicked()), this, SLOT(slotEnter())); 33 | connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived())); 34 | } 35 | 36 | 37 | AddFriends::~AddFriends() 38 | { 39 | tcpSocket->disconnectFromHost(); 40 | } 41 | //在关闭窗口之前,断开与服务器的连接 42 | void AddFriends::closeEvent(QCloseEvent *event) 43 | { 44 | tcpSocket->disconnectFromHost(); 45 | tcpSocket->waitForDisconnected(); 46 | event->accept(); 47 | } 48 | void AddFriends::slotEnter() 49 | { 50 | tcpSocket->connectToHost(*serverIP, port); 51 | if(nameLineEdit->text() == "") 52 | { 53 | QMessageBox::warning(this, tr("Name is empty"), tr("Name is empty")); 54 | return; 55 | } 56 | QString msg = tr(ADDFRIENDS); 57 | toname=nameLineEdit->text(); 58 | msg += username+"+"+toname; 59 | int length=tcpSocket->write(msg.toLatin1(), msg.toLatin1().length()); 60 | if(length != msg.length()) 61 | { 62 | return; 63 | } 64 | this->hide(); 65 | } 66 | 67 | void AddFriends::dataReceived() 68 | { 69 | QByteArray datagram; 70 | datagram.resize(tcpSocket->bytesAvailable()); 71 | tcpSocket->read(datagram.data(), datagram.size()); 72 | QString msg = datagram.data(); 73 | 74 | if(msg == "The name is wrong") 75 | { 76 | QMessageBox::warning(this, tr("the message from server..."), tr("The name is wrong")); 77 | this->show(); 78 | } 79 | else if(msg == "message has been sended") 80 | { 81 | QMessageBox::information(this, tr("the message from server..."), tr("message has been sended")); 82 | tcpSocket->disconnectFromHost(); 83 | } 84 | else if(msg=="you are have been friends!") 85 | { 86 | QMessageBox::information(this, tr("the message from server..."), tr("you are have been friends!")); 87 | this->show(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /chatRoom/addfriends.h: -------------------------------------------------------------------------------- 1 | #ifndef ADDFRIENDS_H 2 | #define ADDFRIENDS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "command.h" 13 | 14 | class AddFriends : public QDialog 15 | { 16 | Q_OBJECT 17 | public: 18 | AddFriends(QWidget *parent = 0); 19 | ~AddFriends(); 20 | public: 21 | QString username; 22 | QString toname; 23 | private: 24 | QGridLayout *mainLayout; 25 | QLabel *nameLabel; 26 | QLineEdit *nameLineEdit; 27 | QPushButton *enterBtn; 28 | void closeEvent(QCloseEvent *event);//关闭事件 29 | int port; 30 | QHostAddress *serverIP; 31 | QTcpSocket *tcpSocket; 32 | 33 | public slots: 34 | void slotEnter(); 35 | void dataReceived(); 36 | }; 37 | 38 | #endif // ADDFRIENDS_H 39 | -------------------------------------------------------------------------------- /chatRoom/chatroom.cpp: -------------------------------------------------------------------------------- 1 | #include "chatroom.h" 2 | #include 3 | #include 4 | 5 | ChatRoom::ChatRoom(QWidget *parent,Qt::WindowFlags f) 6 | : QDialog(parent,f) 7 | { 8 | setWindowTitle(tr("TCP Client")); 9 | contentListWidget = new QListWidget; 10 | sendLineEdit = new QLineEdit; 11 | sendBtn = new QPushButton(tr("Send")); 12 | clearBtn = new QPushButton(tr("Clear")); 13 | enterBtn= new QPushButton(tr("Enter Chat Room")); 14 | mainLayout = new QGridLayout(this); 15 | mainLayout->addWidget(contentListWidget,0,0,1,3); 16 | mainLayout->addWidget(sendLineEdit,1,0); 17 | mainLayout->addWidget(sendBtn,1,1); 18 | mainLayout->addWidget(clearBtn,1,2); 19 | mainLayout->addWidget(enterBtn,2,0,1,3); 20 | 21 | 22 | status = false; 23 | //连接服务器 24 | port = 12345; 25 | IP = "172.29.1.82"; 26 | serverIP = new QHostAddress(); 27 | connect(enterBtn, SIGNAL(clicked()), this, SLOT(slotEnter())); 28 | connect(sendBtn, SIGNAL(clicked()), this, SLOT(slotSend())); 29 | connect(clearBtn, SIGNAL(clicked()), this, SLOT(slotClear())); 30 | sendBtn->setEnabled(false); 31 | } 32 | 33 | ChatRoom::~ChatRoom() 34 | { 35 | } 36 | 37 | void ChatRoom::slotEnter() 38 | { 39 | if(!status) 40 | { 41 | /* 完成输入合法性检验 */ 42 | if(!serverIP->setAddress(IP)) 43 | { 44 | QMessageBox::information(this,tr("error"),tr("server ip address error!")); 45 | return; 46 | } 47 | 48 | /* 创建了一个QTcpSocket类对象,并将信号/槽连接起来 */ 49 | tcpSocket = new QTcpSocket(this); 50 | connect(tcpSocket, SIGNAL(connected()), this, SLOT (slotConnected())); 51 | connect(tcpSocket, SIGNAL(disconnected()), this, SLOT (slotDisconnected ())); 52 | connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived())); 53 | tcpSocket->connectToHost(*serverIP, port); 54 | status = true; 55 | sendBtn->setEnabled(true); 56 | } 57 | else 58 | { 59 | int length = 0; 60 | QString msg = tr(" :Leave Chat Room"); 61 | if((length = tcpSocket->write(msg.toLatin1(),msg. length()))!=msg. length()) 62 | { 63 | return; 64 | } 65 | tcpSocket->disconnectFromHost(); 66 | status = false; //将status状态复位 67 | } 68 | } 69 | 70 | void ChatRoom::slotConnected() 71 | { 72 | enterBtn->setText(tr("leave")); 73 | int length = 0; 74 | QString msg = tr(" :Enter Chat Room"); 75 | if((length = tcpSocket->write(msg.toLatin1(), msg.length())) != msg.length()) 76 | { 77 | return; 78 | } 79 | } 80 | 81 | void ChatRoom::slotSend() 82 | { 83 | if(sendLineEdit->text() == "") 84 | { 85 | return; 86 | } 87 | QString msg = sendLineEdit->text(); 88 | tcpSocket->write(msg.toLatin1(), msg.length()); 89 | sendLineEdit->clear(); 90 | } 91 | 92 | void ChatRoom::slotDisconnected() 93 | { 94 | sendBtn->setEnabled(false); 95 | enterBtn->setText(tr("Enter Chat Room")); 96 | } 97 | 98 | void ChatRoom::slotClear() 99 | { 100 | contentListWidget->clear(); 101 | } 102 | 103 | void ChatRoom::dataReceived() 104 | { 105 | while(tcpSocket->bytesAvailable()>0) 106 | { 107 | QByteArray datagram; 108 | datagram.resize(tcpSocket->bytesAvailable()); 109 | tcpSocket->read(datagram.data(),datagram.size()); 110 | QString msg=datagram.data(); 111 | contentListWidget->addItem(msg.left(datagram.size())); 112 | contentListWidget->scrollToBottom(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /chatRoom/chatroom.h: -------------------------------------------------------------------------------- 1 | #ifndef CHATROOM_H 2 | #define CHATROOM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "command.h" 14 | 15 | class ChatRoom : public QDialog 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | ChatRoom(QWidget *parent = 0,Qt::WindowFlags f=0); 21 | ~ChatRoom(); 22 | 23 | private: 24 | QListWidget *contentListWidget; 25 | QLineEdit *sendLineEdit; 26 | QPushButton *sendBtn; 27 | QPushButton *clearBtn; 28 | QPushButton *enterBtn; 29 | QGridLayout *mainLayout; 30 | bool status; 31 | int port; 32 | QString IP; 33 | QHostAddress *serverIP; 34 | QTcpSocket *tcpSocket; 35 | 36 | public slots: 37 | void slotEnter(); 38 | void slotConnected(); 39 | void slotDisconnected(); 40 | void dataReceived(); 41 | void slotSend(); 42 | void slotClear(); 43 | }; 44 | 45 | 46 | #endif // CHATROOM_H 47 | -------------------------------------------------------------------------------- /chatRoom/command.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMAND_H 2 | #define COMMAND_H 3 | 4 | #define SERVER_IP "122.51.90.199" 5 | #define REGISTER "1" 6 | #define LOGIN "2" 7 | #define MESSAGE "3" 8 | #define ADDFRIENDS "4" 9 | #define ADDREQUEST "5" 10 | #define ACCEPT "6" 11 | #define REFUSE "7" 12 | #define FRIENDSLIST "8" 13 | #define ONLINE "9" 14 | #define ONLINESTATE "o" 15 | #define PICCHANGE "p" 16 | #endif // COMMAND_H 17 | -------------------------------------------------------------------------------- /chatRoom/drawer.cpp: -------------------------------------------------------------------------------- 1 | #include "drawer.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | Drawer::Drawer(QWidget *parent, Qt::WindowFlags f) 8 | :QToolBox(parent,f) 9 | { 10 | this->setWindowFlags(Qt::FramelessWindowHint);//去掉边框 11 | setWindowTitle(tr("Chat Room")); 12 | setWindowIcon(QPixmap(":/images/ChatRoom.jpg")); 13 | 14 | initialMapstylestring(); 15 | tabWidget=new QTabWidget(this); 16 | QWidget *sysWidget=new QWidget; 17 | QVBoxLayout *sysLayout=new QVBoxLayout(sysWidget); 18 | addFriendsBtn = new QPushButton(tr("添加好友")); 19 | connect(addFriendsBtn, SIGNAL(clicked()), this, SLOT(slotAddFriends())); 20 | QPushButton *EnterChatRoom=new QPushButton(tr("聊天室")); 21 | connect(EnterChatRoom, SIGNAL(clicked()), this, SLOT(showChatWidget1())); 22 | QPushButton *QuitButton=new QPushButton(tr("退出客户端")); 23 | connect(QuitButton, SIGNAL(clicked()), this, SLOT(Quit())); 24 | SelectMapStytle=new QComboBox(this); 25 | SelectMapStytle->addItem(tr("修改头像"));//项目编号从0开始 26 | SelectMapStytle->addItem(tr("汪老板")); 27 | SelectMapStytle->addItem(tr("刘老板")); 28 | SelectMapStytle->addItem(tr("赵老师")); 29 | SelectMapStytle->addItem(tr("周老师")); 30 | SelectMapStytle->addItem(tr("小飞飞")); 31 | SelectMapStytle->addItem(tr("BOSS")); 32 | SelectMapStytle->addItem(tr("军军")); 33 | SelectMapStytle->addItem(tr("军军2号")); 34 | SelectMapStytle->addItem(tr("小飞飞2号")); 35 | SelectMapStytle->addItem(tr("汪老板2号")); 36 | SelectMapStytle->setCurrentIndex(0); 37 | connect(SelectMapStytle,SIGNAL(currentIndexChanged(int)),this,SLOT(MapStytleSet())); 38 | sysLayout->setMargin(20); 39 | sysLayout->setAlignment(Qt::AlignTop);//设置顶部对齐 40 | sysLayout->addWidget(addFriendsBtn); 41 | sysLayout->addWidget(EnterChatRoom); 42 | sysLayout->addWidget(SelectMapStytle); 43 | sysLayout->addWidget(QuitButton); 44 | sysWidget->setLayout(sysLayout); 45 | 46 | myFriends=new QWidget; 47 | friLayout=new QVBoxLayout(myFriends); 48 | myFriends->setLayout(friLayout); 49 | friLayout->setAlignment(Qt::AlignTop);//设置顶部对齐 50 | 51 | tabWidget->addTab(sysWidget,"系统功能"); 52 | tabWidget->addTab(myFriends,"我的好友"); 53 | 54 | toolBtn1 = new QToolButton(this); 55 | toolBtn1->setIcon(QPixmap(":/images/qq.png")); 56 | toolBtn1->setIconSize(QPixmap(":/images/qq.png").size()); 57 | toolBtn1->setAutoRaise(true); 58 | toolBtn1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 59 | //toolBtn1->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 60 | //connect(toolBtn1, SIGNAL(clicked()), this, SLOT(showChatWidget1())); 61 | 62 | toolBtn2 = new QToolButton(this); 63 | toolBtn2->setIcon(QPixmap(":/images/1.png")); 64 | //toolBtn2->setIconSize(QPixmap(":/images/1.png").size()); 65 | toolBtn2->setAutoRaise(true); 66 | toolBtn2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 67 | toolBtn2->setText("new message"); 68 | toolBtn2->hide(); 69 | connect(toolBtn2, SIGNAL(clicked()), this, SLOT(showaddfriendWidget())); 70 | 71 | QGroupBox *groupBox = new QGroupBox; 72 | QVBoxLayout *layout = new QVBoxLayout(groupBox); 73 | layout->setMargin(0); 74 | layout->setAlignment(Qt::AlignLeft); 75 | layout->addWidget(toolBtn1); 76 | layout->addWidget(tabWidget); 77 | layout->addWidget(toolBtn2); 78 | //layout->addStretch(); //插入一个占位符 79 | 80 | this->addItem((QWidget*)groupBox, tr("Client")); 81 | addflag=false; 82 | refuseflag=false; 83 | changefunc=false; 84 | PicChangeflag=false; 85 | 86 | getfdlTimer=new QTimer(this); 87 | connect(getfdlTimer,SIGNAL(timeout()),this,SLOT(getFDL())); 88 | getfdlTimer->start(10); 89 | 90 | havedoneTimer=new QTimer(this); 91 | connect(havedoneTimer,SIGNAL(timeout()),this,SLOT(CheckFlag())); 92 | havedoneTimer->start(100); 93 | 94 | 95 | onlineStateTimer=new QTimer(this); 96 | connect(onlineStateTimer,SIGNAL(timeout()),this,SLOT(CheckonlineState())); 97 | 98 | users=new userInfo[20]; 99 | 100 | } 101 | 102 | void Drawer::initialMapstylestring() 103 | { 104 | MapStytle[0]=":/images/qq.png"; 105 | MapStytle[1]=":/images/w.png"; 106 | MapStytle[2]=":/images/l.png"; 107 | MapStytle[3]=":/images/zz.png"; 108 | MapStytle[4]=":/images/z.png"; 109 | MapStytle[5]=":/images/m.png"; 110 | MapStytle[6]=":/images/boss.png"; 111 | MapStytle[7]=":/images/jj.png"; 112 | MapStytle[8]=":/images/jj2.png"; 113 | MapStytle[9]=":/images/m2.png"; 114 | MapStytle[10]=":/images/w2.png"; 115 | } 116 | void Drawer::initialfriendsList() 117 | { 118 | //qDebug()<<"initial List"; 119 | int i; 120 | if(!friendList.isEmpty()) 121 | { 122 | friendsListButtons=new QToolButton *[friendList.size()+10]; 123 | for(i=0;i<(friendList.size()+10);i++) 124 | { 125 | //qDebug()<<"if i:"<setText(friendName); 135 | friendsListButtons[friendsNum]->setIcon(QPixmap(":/images/qq.png")); 136 | friendsListButtons[friendsNum]->setIconSize(QPixmap(":/images/qq.png").size()); 137 | friendsListButtons[friendsNum]->setAutoRaise(true); 138 | friendsListButtons[friendsNum]->setEnabled(false); 139 | friendsListButtons[friendsNum]->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 140 | friLayout->addWidget(friendsListButtons[friendsNum]); 141 | friendsNum++; 142 | } 143 | checkOnlineState=new onlineState; 144 | onlineStateTimer->start(5000); 145 | } 146 | void Drawer::CheckonlineState() 147 | { 148 | if(checkOnlineState->StateUpdateDone) 149 | { 150 | users=checkOnlineState->users; 151 | int i,j; 152 | //qDebug()<<"--------------------friendsNum-----------------------"<text(); 156 | //qDebug()<<"---friendName---"<count;j++) 158 | { 159 | if(checkOnlineState->users[j].name==friendName.toStdString()) 160 | { 161 | if(checkOnlineState->users[j].online==1) 162 | { 163 | //friendsListButtons[i]->setText(friendName); 164 | friendsListButtons[i]->setEnabled(true); 165 | } 166 | else 167 | { 168 | friendsListButtons[i]->setEnabled(false); 169 | } 170 | friendsListButtons[i]->setIcon(QPixmap(MapStytle[checkOnlineState->users[j].pic])); 171 | friendsListButtons[i]->setIconSize(QPixmap(MapStytle[checkOnlineState->users[j].pic]).size()); 172 | } 173 | if(checkOnlineState->users[j].name==username.toStdString()) 174 | { 175 | //qDebug()<<"---Name---"<setIcon(QPixmap(MapStytle[checkOnlineState->users[j].pic])); 177 | toolBtn1->setIconSize(QPixmap(MapStytle[checkOnlineState->users[j].pic]).size()); 178 | } 179 | 180 | } 181 | 182 | } 183 | checkOnlineState->StateUpdateDone=false; 184 | } 185 | //onlineStateTimer->stop(); 186 | } 187 | 188 | void Drawer::MapStytleSet() 189 | { 190 | toolBtn1->setIcon(QPixmap(MapStytle[SelectMapStytle->currentIndex()])); 191 | toolBtn1->setIconSize(QPixmap(MapStytle[SelectMapStytle->currentIndex()]).size()); 192 | PicChangeflag=true; 193 | } 194 | 195 | void Drawer::showChatWidget1() 196 | { 197 | chat1 = new TcpClient(); 198 | chat1->username = toolBtn1->text(); 199 | chat1->setWindowTitle(toolBtn1->text()); 200 | chat1->show(); 201 | } 202 | void Drawer::getFDL() 203 | { 204 | getFriendsList=new friendsList; 205 | getFriendsList->username=username; 206 | getFriendsList->sendRQ(); 207 | getfdlTimer->stop(); 208 | } 209 | void Drawer::CheckFlag() 210 | { 211 | if(getFriendsList->havedoneFlag) 212 | { 213 | friendList=getFriendsList->friendList; 214 | initialfriendsList(); 215 | havedoneTimer->stop(); 216 | //getFriendsList->havedoneFlag=false; 217 | } 218 | //qDebug()<<"checking..."<havedoneFlag; 219 | } 220 | void Drawer::slotAddFriends() 221 | { 222 | addFriends = new AddFriends(); 223 | addFriends->username=username; 224 | addFriends->show(); 225 | 226 | } 227 | void Drawer::showaddfriendWidget() 228 | { 229 | if(!changefunc) 230 | { 231 | toolBtn2->hide(); 232 | QString msg; 233 | msg+=fromname+" want to add you as a friend,do you agree?"; 234 | QMessageBox message(QMessageBox::Information,"addfriend request...",msg,QMessageBox::Yes|QMessageBox::No,this); 235 | if(message.exec()==QMessageBox::Yes) 236 | { 237 | addflag=true; 238 | int currNum=friendsNum; 239 | //qDebug()<<"fromname "<setText(fromname); 241 | friendsListButtons[currNum]->setIcon(QPixmap(":/images/qq.png")); 242 | friendsListButtons[currNum]->setIconSize(QPixmap(":/images/qq.png").size()); 243 | friendsListButtons[currNum]->setAutoRaise(true); 244 | friendsListButtons[currNum]->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 245 | friLayout->addWidget(friendsListButtons[currNum]); 246 | friendsNum++; 247 | } 248 | else 249 | { 250 | refuseflag=true; 251 | } 252 | } 253 | else 254 | { 255 | toolBtn2->hide(); 256 | QMessageBox::information(this, tr("the message from server..."), tr("your requet had been refused...")); 257 | } 258 | } 259 | //重写鼠标点击和移动事件,使没有边框的窗口可以通过鼠标移动 260 | void Drawer::mousePressEvent(QMouseEvent *event) 261 | { 262 | this->windowPos = this->pos(); // 获得部件当前位置 263 | this->mousePos = event->globalPos(); // 获得鼠标位置 264 | this->dPos = mousePos - windowPos; // 移动后部件所在的位置 265 | } 266 | 267 | void Drawer::mouseMoveEvent(QMouseEvent *event) 268 | { 269 | this->move(event->globalPos() - this->dPos); 270 | } 271 | void Drawer::Quit() 272 | { 273 | QMessageBox message(QMessageBox::Information,"退出客户端","是否退出?",QMessageBox::Yes|QMessageBox::No,this); 274 | message.setButtonText(QMessageBox::Yes, QString("确 定")); 275 | message.setButtonText(QMessageBox::No, QString("返 回")); 276 | if(message.exec()==QMessageBox::Yes) 277 | { 278 | qApp->quit();//退出当前应用程序,需要 QApplication的头文件 279 | } 280 | else 281 | { 282 | return; 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /chatRoom/drawer.h: -------------------------------------------------------------------------------- 1 | #ifndef DRAWER_H 2 | #define DRAWER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "tcpclient.h" 17 | #include "addfriends.h" 18 | #include "friendslist.h" 19 | #include "onlinestate.h" 20 | #include "command.h" 21 | class Drawer : public QToolBox 22 | { 23 | Q_OBJECT 24 | public: 25 | Drawer(QWidget *parent = 0, Qt::WindowFlags f = 0); 26 | 27 | QString username; 28 | QString fromname; 29 | QString toname; 30 | QString onlinename; 31 | QTabWidget *tabWidget; 32 | QToolButton *toolBtn1; 33 | QToolButton *toolBtn2; 34 | QPushButton *addFriendsBtn; 35 | QComboBox *SelectMapStytle; 36 | QWidget *myFriends; 37 | QVBoxLayout *friLayout; 38 | //QLabel *picSelect; 39 | bool addflag; 40 | bool refuseflag; 41 | bool changefunc; 42 | bool PicChangeflag; 43 | QQueue friendList; 44 | QTimer *havedoneTimer; 45 | QToolButton **friendsListButtons; 46 | int friendsNum; 47 | AddFriends *addFriends; 48 | private slots: 49 | void showChatWidget1(); 50 | void slotAddFriends(); 51 | void showaddfriendWidget(); 52 | void MapStytleSet(); 53 | void getFDL(); 54 | void CheckFlag(); 55 | void CheckonlineState(); 56 | void Quit(); 57 | private: 58 | QPoint windowPos;//窗口位置 59 | QPoint mousePos;//鼠标位置 60 | QPoint dPos;//鼠标移动后的位置 61 | void mousePressEvent(QMouseEvent *event);//鼠标按下事件(用于移动主界面) 62 | void mouseMoveEvent(QMouseEvent *event);//鼠标移动事件 63 | void initialMapstylestring(); 64 | void initialfriendsList(); 65 | QString MapStytle[11]; 66 | TcpClient *chat1; 67 | friendsList *getFriendsList; 68 | onlineState *checkOnlineState; 69 | QTimer *getfdlTimer; 70 | QTimer *onlineStateTimer; 71 | struct userInfo *users;//有嫌疑 72 | }; 73 | 74 | #endif // DRAWER_H 75 | -------------------------------------------------------------------------------- /chatRoom/friendslist.cpp: -------------------------------------------------------------------------------- 1 | #include "friendslist.h" 2 | 3 | friendsList::friendsList(QWidget *parent) : QWidget(parent) 4 | { 5 | //连接服务器 6 | port = 12345; 7 | serverIP = new QHostAddress(); 8 | QString ip = SERVER_IP; 9 | serverIP->setAddress(ip); 10 | tcpSocket=new QTcpSocket(this); 11 | tcpSocket->connectToHost(*serverIP, port); 12 | connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived())); 13 | havedoneFlag=false; 14 | } 15 | friendsList::~friendsList() 16 | { 17 | tcpSocket->disconnectFromHost(); 18 | } 19 | void friendsList::sendRQ() 20 | { 21 | QString msg = tr(FRIENDSLIST); 22 | msg+=username; 23 | int length=tcpSocket->write(msg.toLatin1(), msg.toLatin1().length()); 24 | if(length != msg.toLatin1().length()) 25 | { 26 | return; 27 | } 28 | } 29 | void friendsList::dataReceived() 30 | { 31 | QByteArray datagram; 32 | datagram.resize(tcpSocket->bytesAvailable()); 33 | tcpSocket->read(datagram.data(), datagram.size()); 34 | QString msg = datagram.data(); 35 | //qDebug()<<"msg:"<disconnectFromHost(); 53 | } 54 | 55 | -------------------------------------------------------------------------------- /chatRoom/friendslist.h: -------------------------------------------------------------------------------- 1 | #ifndef FRIENDSLIST_H 2 | #define FRIENDSLIST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "command.h" 9 | class friendsList : public QWidget 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit friendsList(QWidget *parent = 0); 14 | ~friendsList(); 15 | void sendRQ(); 16 | QString username; 17 | bool havedoneFlag; 18 | QQueue friendList; 19 | QTcpSocket *tcpSocket; 20 | private: 21 | int port; 22 | QHostAddress *serverIP; 23 | private slots: 24 | void dataReceived(); 25 | }; 26 | 27 | #endif // FRIENDSLIST_H 28 | -------------------------------------------------------------------------------- /chatRoom/images.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/ChatRoom.jpg 4 | images/1.png 5 | images/qq.png 6 | images/w.png 7 | images/l.png 8 | images/z.png 9 | images/zz.png 10 | images/m.png 11 | images/boss.png 12 | images/jj.png 13 | images/jj2.png 14 | images/m2.png 15 | images/w2.png 16 | 17 | 18 | -------------------------------------------------------------------------------- /chatRoom/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/1.png -------------------------------------------------------------------------------- /chatRoom/images/ChatRoom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/ChatRoom.jpg -------------------------------------------------------------------------------- /chatRoom/images/Linux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/Linux.jpg -------------------------------------------------------------------------------- /chatRoom/images/boss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/boss.png -------------------------------------------------------------------------------- /chatRoom/images/jj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/jj.png -------------------------------------------------------------------------------- /chatRoom/images/jj2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/jj2.png -------------------------------------------------------------------------------- /chatRoom/images/l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/l.png -------------------------------------------------------------------------------- /chatRoom/images/liu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/liu.png -------------------------------------------------------------------------------- /chatRoom/images/m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/m.png -------------------------------------------------------------------------------- /chatRoom/images/m2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/m2.png -------------------------------------------------------------------------------- /chatRoom/images/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/qq.png -------------------------------------------------------------------------------- /chatRoom/images/w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/w.png -------------------------------------------------------------------------------- /chatRoom/images/w2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/w2.png -------------------------------------------------------------------------------- /chatRoom/images/z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/z.png -------------------------------------------------------------------------------- /chatRoom/images/zz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/chatRoom/images/zz.png -------------------------------------------------------------------------------- /chatRoom/information.h: -------------------------------------------------------------------------------- 1 | #ifndef INFORMATION_H 2 | #define INFORMATION_H 3 | 4 | #include 5 | 6 | QString username; 7 | 8 | #endif // INFORMATION_H 9 | -------------------------------------------------------------------------------- /chatRoom/main.cpp: -------------------------------------------------------------------------------- 1 | #include "sign.h" 2 | #include "drawer.h" 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication a(argc, argv); 9 | 10 | Sign s; 11 | s.show(); 12 | 13 | return a.exec(); 14 | } 15 | -------------------------------------------------------------------------------- /chatRoom/onlinestate.cpp: -------------------------------------------------------------------------------- 1 | #include "onlinestate.h" 2 | 3 | onlineState::onlineState(QWidget *parent) : QWidget(parent) 4 | { 5 | //连接服务器 6 | port = 12345; 7 | serverIP = new QHostAddress(); 8 | QString ip = SERVER_IP; 9 | serverIP->setAddress(ip); 10 | tcpSocket=new QTcpSocket(this); 11 | tcpSocket->connectToHost(*serverIP, port); 12 | connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived())); 13 | sendRQ(); 14 | StateUpdateDone=false; 15 | SendRqTimer=new QTimer(this); 16 | connect(SendRqTimer,SIGNAL(timeout()),this,SLOT(senRq())); 17 | SendRqTimer->start(15000); 18 | } 19 | void onlineState::sendRQ() 20 | { 21 | QString msg = tr(ONLINESTATE); 22 | tcpSocket->write(msg.toLatin1(), msg.toLatin1().length()); 23 | } 24 | void onlineState::senRq() 25 | { 26 | tcpSocket->connectToHost(*serverIP, port); 27 | sendRQ(); 28 | } 29 | void onlineState::dataReceived() 30 | { 31 | QByteArray datagram; 32 | datagram.resize(tcpSocket->bytesAvailable()); 33 | tcpSocket->read(datagram.data(), datagram.size()); 34 | QString msg = datagram.data(); 35 | //qDebug()<<"online State msg:"<disconnectFromHost(); 53 | } 54 | -------------------------------------------------------------------------------- /chatRoom/onlinestate.h: -------------------------------------------------------------------------------- 1 | #ifndef ONLINESTATE_H 2 | #define ONLINESTATE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "command.h" 10 | struct userInfo 11 | { 12 | std::string name; 13 | int online; 14 | int pic; 15 | }; 16 | class onlineState : public QWidget 17 | { 18 | Q_OBJECT 19 | public: 20 | explicit onlineState(QWidget *parent = 0); 21 | void sendRQ(); 22 | //QString username; 23 | QTimer *SendRqTimer; 24 | struct userInfo *users; 25 | int count; 26 | bool StateUpdateDone; 27 | private: 28 | int port; 29 | QHostAddress *serverIP; 30 | QTcpSocket *tcpSocket; 31 | private slots: 32 | void dataReceived(); 33 | void senRq(); 34 | }; 35 | 36 | #endif // ONLINESTATE_H 37 | -------------------------------------------------------------------------------- /chatRoom/sign.cpp: -------------------------------------------------------------------------------- 1 | #include "sign.h" 2 | #include "drawer.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | Sign::Sign(QWidget *parent) 9 | : QDialog(parent) 10 | { 11 | setWindowTitle(tr("聊天室客户端")); 12 | this->setFixedSize(400,200); 13 | 14 | registerBtn = new QPushButton(tr("注册")); 15 | LogInBtn = new QPushButton(tr("登录")); 16 | connectBtn = new QPushButton(tr("连接服务器")); 17 | nameLabel = new QLabel(tr("Name(英文):")); 18 | passwordLabel = new QLabel(tr("Password:")); 19 | // ServerIPLabel=new QLabel(tr("ServerIP")); 20 | // ServerIPEdit=new QLineEdit(); 21 | nameLineEdit = new QLineEdit(); 22 | passwordLineEdit = new QLineEdit(); 23 | passwordLineEdit->setEchoMode(QLineEdit::Password); 24 | tcpSocket = new QTcpSocket(this); 25 | 26 | 27 | mainLayout = new QGridLayout(this); 28 | mainLayout->addWidget(nameLabel, 0, 0); 29 | mainLayout->addWidget(nameLineEdit, 0, 1, 1, 2); 30 | mainLayout->addWidget(passwordLabel, 1, 0); 31 | mainLayout->addWidget(passwordLineEdit, 1, 1, 1, 2); 32 | // mainLayout->addWidget(ServerIPLabel, 2, 0); 33 | // mainLayout->addWidget(ServerIPEdit, 2, 1, 1, 2); 34 | mainLayout->addWidget(registerBtn, 2, 0); 35 | mainLayout->addWidget(LogInBtn, 2, 1); 36 | mainLayout->addWidget(connectBtn, 2, 2); 37 | //mainLayout->setContentsMargins(0,0,0,0);//让布局紧贴主窗口,不留空白 38 | //mainLayout->setSpacing(0); 39 | 40 | addfriendTimer=new QTimer(this); 41 | connect(addfriendTimer,SIGNAL(timeout()),this,SLOT(Checkflag())); 42 | 43 | PicChangeTimer=new QTimer(this); 44 | connect(PicChangeTimer,SIGNAL(timeout()),this,SLOT(CheckPicChange())); 45 | 46 | registerBtn->setEnabled(false); 47 | LogInBtn->setEnabled(false); 48 | 49 | connect(connectBtn, SIGNAL(clicked()), this, SLOT(slotConnect())); 50 | connect(registerBtn, SIGNAL(clicked()), this, SLOT(slotRegister())); 51 | connect(LogInBtn, SIGNAL(clicked()), this, SLOT(slotLogIn())); 52 | connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived())); 53 | connect(tcpSocket, SIGNAL(connected()), this, SLOT(connected())); 54 | } 55 | 56 | Sign::~Sign() 57 | { 58 | tcpSocket->disconnectFromHost(); 59 | } 60 | void Sign::slotConnect() 61 | { 62 | if(nameLineEdit->text() == "" || passwordLineEdit->text() == "") 63 | { 64 | QMessageBox::warning(this, tr("error"), tr("Name or Password is empty!")); 65 | return; 66 | } 67 | 68 | //连接服务器 69 | port = 12345; 70 | serverIP = new QHostAddress(); 71 | QString ip = SERVER_IP; 72 | serverIP->setAddress(ip); 73 | tcpSocket->connectToHost(*serverIP, port); 74 | } 75 | 76 | void Sign::connected() 77 | { 78 | connectBtn->setEnabled(false); 79 | registerBtn->setEnabled(true); 80 | LogInBtn->setEnabled(true); 81 | } 82 | 83 | 84 | void Sign::slotRegister() 85 | { 86 | QString msg = tr(REGISTER); 87 | username = nameLineEdit->text(); 88 | QString password = passwordLineEdit->text(); 89 | msg += username + '\t' + password; 90 | int length = tcpSocket->write(msg.toLatin1(), msg.toLatin1().length()); 91 | if(length != msg.toUtf8().length()) 92 | { 93 | return; 94 | } 95 | } 96 | 97 | void Sign::slotLogIn() 98 | { 99 | QString msg = tr(LOGIN); 100 | username = nameLineEdit->text(); 101 | QString password = passwordLineEdit->text(); 102 | msg += username + '\t' + password; 103 | int length = tcpSocket->write(msg.toLatin1(), msg.toLatin1().length()); 104 | if(length != msg.toUtf8().length()) 105 | { 106 | return; 107 | } 108 | } 109 | 110 | void Sign::dataReceived() 111 | { 112 | QByteArray datagram; 113 | datagram.resize(tcpSocket->bytesAvailable()); 114 | tcpSocket->read(datagram.data(), datagram.size()); 115 | QString msg = datagram.data(); 116 | 117 | //qDebug()<<"msg [0]:"<hide(); 123 | 124 | drawer = new Drawer(); 125 | drawer->toolBtn1->setText(username); 126 | drawer->username=username; 127 | //drawer->resize(250, 500); 128 | drawer->setFixedSize(250,500); 129 | drawer->show(); 130 | PicChangeTimer->start(2000); 131 | } 132 | else if(msg == "REGISTER SUCCESS") 133 | { 134 | QMessageBox::information(this, tr("register success, now you can log in"), tr("register success, now you can log in")); 135 | } 136 | else if(msg.contains("*AdDR.",Qt::CaseSensitive)) 137 | { 138 | std::string rec=msg.toStdString(); 139 | auto it = rec.find('+'); 140 | //qDebug()<<"it "<fromname=fromname; 146 | drawer->toname=toname; 147 | drawer->toolBtn2->show(); 148 | addfriendTimer->start(10); 149 | } 150 | else if(msg=="your requet had been refused...") 151 | { 152 | drawer->toolBtn2->show(); 153 | drawer->changefunc=true; 154 | } 155 | else if(msg.contains("*ACCEPT.",Qt::CaseSensitive)) 156 | { 157 | int currNum=drawer->friendsNum; 158 | qDebug()<<"toname:"<addFriends->toname; 159 | drawer->friendsListButtons[currNum]->setText(drawer->addFriends->toname); 160 | drawer->friendsListButtons[currNum]->setIcon(QPixmap(":/images/qq.png")); 161 | drawer->friendsListButtons[currNum]->setIconSize(QPixmap(":/images/qq.png").size()); 162 | drawer->friendsListButtons[currNum]->setAutoRaise(true); 163 | drawer-> friendsListButtons[currNum]->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 164 | drawer->friLayout->addWidget(drawer->friendsListButtons[currNum]); 165 | drawer->friendsNum++; 166 | } 167 | else if(msg=="The name has been registered") 168 | { 169 | QMessageBox::information(this, tr("The name has been registered"), tr("The name has been registered")); 170 | } 171 | else if(msg=="You have to register first") 172 | { 173 | QMessageBox::information(this, tr("You have to register first"), tr("You have to register first")); 174 | } 175 | else if(msg=="password is wrong") 176 | { 177 | QMessageBox::information(this, tr("password is wrong"), tr("password is wrong")); 178 | } 179 | // else if(msg.contains("*ONLINE.",Qt::CaseSensitive)) 180 | // { 181 | // qDebug()<<"msg :"<onlinename=onlineName; 188 | // drawer->onlineTimer->start(500); 189 | // } 190 | } 191 | void Sign::Checkflag() 192 | { 193 | if(drawer->addflag) 194 | { 195 | QString msg = tr(ACCEPT); 196 | msg+=fromname+"\t"+toname+" have been friends"; 197 | int length=0; 198 | if((length = tcpSocket->write(msg.toLatin1(),msg.toLatin1(). length())) != msg.toLatin1().length()) 199 | { 200 | return; 201 | } 202 | addfriendTimer->stop(); 203 | fromname.clear(); 204 | //toname.clear(); 205 | drawer->addflag=false; 206 | } 207 | if(drawer->refuseflag) 208 | { 209 | QString msg = tr(REFUSE); 210 | msg+=fromname; 211 | int length=0; 212 | if((length = tcpSocket->write(msg.toLatin1(),msg.toLatin1(). length())) != msg.toLatin1().length()) 213 | { 214 | return; 215 | } 216 | addfriendTimer->stop(); 217 | fromname.clear(); 218 | toname.clear(); 219 | drawer->refuseflag=false; 220 | } 221 | } 222 | void Sign::CheckPicChange() 223 | { 224 | if(drawer->PicChangeflag) 225 | { 226 | QString msg = tr(PICCHANGE); 227 | QString pic=QString::number(drawer->SelectMapStytle->currentIndex(),10); 228 | msg+=drawer->username+":"+pic; 229 | tcpSocket->write(msg.toLatin1(),msg.toLatin1(). length()); 230 | drawer->PicChangeflag=false; 231 | } 232 | 233 | } 234 | -------------------------------------------------------------------------------- /chatRoom/sign.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGN_H 2 | #define SIGN_H 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "command.h" 16 | #include "drawer.h" 17 | 18 | class Sign : public QDialog 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | Sign(QWidget *parent = 0); 24 | ~Sign(); 25 | 26 | private: 27 | QGridLayout *mainLayout; 28 | QLabel *nameLabel; 29 | QLabel *passwordLabel; 30 | QPushButton *connectBtn; 31 | QLineEdit *nameLineEdit; 32 | QLineEdit *passwordLineEdit; 33 | QPushButton *registerBtn; 34 | QPushButton *LogInBtn; 35 | QTimer *addfriendTimer; 36 | QString fromname; 37 | QString toname; 38 | int port; 39 | QHostAddress *serverIP; 40 | QTcpSocket *tcpSocket; 41 | 42 | QString username; 43 | Drawer *drawer; 44 | QTimer *PicChangeTimer; 45 | public slots: 46 | void slotRegister(); 47 | void slotLogIn(); 48 | void slotConnect(); 49 | void dataReceived(); 50 | void connected(); 51 | void Checkflag(); 52 | void CheckPicChange(); 53 | }; 54 | 55 | #endif // SIGN_H 56 | -------------------------------------------------------------------------------- /chatRoom/tcpclient.cpp: -------------------------------------------------------------------------------- 1 | #include "tcpclient.h" 2 | #include 3 | #include 4 | 5 | TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f) 6 | : QDialog(parent,f) 7 | { 8 | setWindowTitle(tr("TCP Client")); 9 | resize(500, 300); 10 | contentListWidget = new QListWidget; 11 | sendLineEdit = new QLineEdit; 12 | sendBtn = new QPushButton(tr("Send")); 13 | clearBtn = new QPushButton(tr("Clear")); 14 | mainLayout = new QGridLayout(this); 15 | mainLayout->addWidget(contentListWidget,0,0,1,3); 16 | mainLayout->addWidget(sendLineEdit,1,0); 17 | mainLayout->addWidget(sendBtn,1,1); 18 | mainLayout->addWidget(clearBtn,1,2); 19 | port = 12345; 20 | IP = SERVER_IP; 21 | serverIP = new QHostAddress(); 22 | connect(sendBtn,SIGNAL(clicked()),this,SLOT(slotSend())); 23 | connect(clearBtn,SIGNAL(clicked()),this,SLOT(slotClear())); 24 | 25 | if(!serverIP->setAddress(IP)) 26 | { 27 | QMessageBox::information(this,tr("error"),tr("server ip address error!")); 28 | return; 29 | } 30 | /* 创建了一个QTcpSocket类对象,并将信号/槽连接起来 */ 31 | tcpSocket = new QTcpSocket(this); 32 | connect(tcpSocket,SIGNAL(connected()),this,SLOT (slotConnected())); 33 | connect(tcpSocket,SIGNAL(readyRead()),this,SLOT (dataReceived())); 34 | tcpSocket->connectToHost(*serverIP ,port); 35 | } 36 | 37 | TcpClient::~TcpClient() 38 | { 39 | 40 | } 41 | //在关闭窗口之前,断开与服务器的连接 42 | void TcpClient::closeEvent(QCloseEvent *event) 43 | { 44 | tcpSocket->disconnectFromHost(); 45 | tcpSocket->waitForDisconnected(); 46 | event->accept(); 47 | } 48 | 49 | void TcpClient::slotConnected() 50 | { 51 | sendBtn->setEnabled(true); 52 | int length=0; 53 | QString msg = tr(MESSAGE); 54 | msg += username + ": Enter Chat Room"; 55 | if((length = tcpSocket->write(msg.toLatin1(),msg.toLatin1(). length())) != msg.toLatin1().length()) 56 | { 57 | return; 58 | } 59 | } 60 | 61 | void TcpClient::slotSend() 62 | { 63 | // QTextCodec::setCodecForTr( QTextCodec::codecForLocale() ); 64 | // QTextCodec::setCodecForCStrings( QTextCodec::codecForLocale() ); 65 | //QTextCodec *code= QTextCodec::codecForName("UTF-8"); 66 | //QString strtest = "你好Test"; 67 | //QByteArray bytest = code->fromUnicode( strtest ); 68 | 69 | if(sendLineEdit->text() == "") 70 | { 71 | return; 72 | } 73 | QString msg = tr(MESSAGE); 74 | msg += username + ": " + sendLineEdit->text(); 75 | //qDebug()<write(msg.toUtf8(), msg.toUtf8().length());//发送的数据转换为utf-8格式(网络字节序,中文也能识别) 77 | //qDebug()<<"have writen!"; 78 | sendLineEdit->clear(); 79 | } 80 | 81 | void TcpClient::slotClear() 82 | { 83 | contentListWidget->clear(); 84 | } 85 | 86 | void TcpClient::dataReceived() 87 | { 88 | while(tcpSocket->bytesAvailable() > 0) 89 | { 90 | QByteArray datagram; 91 | datagram.resize(tcpSocket->bytesAvailable()); 92 | tcpSocket->read(datagram.data(),datagram.size()); 93 | QString msg = datagram.data(); 94 | contentListWidget->addItem(msg.left(datagram.size())); 95 | contentListWidget->scrollToBottom(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /chatRoom/tcpclient.h: -------------------------------------------------------------------------------- 1 | #ifndef TCPCLIENT_H 2 | #define TCPCLIENT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "command.h" 15 | class TcpClient : public QDialog 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | TcpClient(QWidget *parent = 0,Qt::WindowFlags f=0); 21 | ~TcpClient(); 22 | QString username; 23 | 24 | private: 25 | QListWidget *contentListWidget; 26 | QLineEdit *sendLineEdit; 27 | QPushButton *sendBtn; 28 | QPushButton *clearBtn; 29 | QGridLayout *mainLayout; 30 | int port; 31 | QString IP; 32 | QHostAddress *serverIP; 33 | QTcpSocket *tcpSocket; 34 | void closeEvent(QCloseEvent *event);//关闭事件 35 | public slots: 36 | void slotConnected(); 37 | void dataReceived(); 38 | void slotSend(); 39 | void slotClear(); 40 | }; 41 | 42 | #endif // TCPCLIENT_H 43 | -------------------------------------------------------------------------------- /chatRoom/widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | #include "ui_widget.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | Widget::Widget(QWidget *parent, QString usrname) : 12 | QWidget(parent), 13 | ui(new Ui::Widget) 14 | { 15 | ui->setupUi(this); 16 | uName = usrname; 17 | port = 12345; 18 | udpSocket = new QUdpSocket(this); 19 | udpSocket->bind(port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint); 20 | connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); 21 | connect(ui->sendBtn, SIGNAL(clicked()), this, SLOT(on_sendBtn_clicked())); 22 | sndMsg(UsrEnter); 23 | } 24 | 25 | Widget::~Widget() 26 | { 27 | delete ui; 28 | } 29 | 30 | 31 | void Widget::sndMsg(MsgType type, QString srvaddr) 32 | { 33 | QByteArray data; 34 | QDataStream out(&data, QIODevice::WriteOnly); 35 | QString address = getIP(); 36 | out << type << getUsr(); 37 | switch(type) 38 | { 39 | case Msg: 40 | if(ui->msgTxtEdit->toPlainText() == "") 41 | { 42 | return; 43 | } 44 | out << address << getMsg(); 45 | ui->msgBrowser->verticalScrollBar()->setValue(ui->msgBrowser->verticalScrollBar()->maximum()); 46 | break; 47 | case UsrEnter: 48 | out << address; 49 | break; 50 | case UsrLeft: 51 | break; 52 | case FileName: { 53 | break; 54 | } 55 | case Refuse: 56 | break; 57 | } 58 | 59 | udpSocket->writeDatagram(data, data.length(), QHostAddress::Broadcast, port); 60 | } 61 | 62 | 63 | void Widget::processPendingDatagrams() 64 | { 65 | while(udpSocket->hasPendingDatagrams()) 66 | { 67 | QByteArray datagram; 68 | //获取当前可供读取的UDP报文大小,并据此大小分配接收缓冲区 69 | datagram.resize(udpSocket->pendingDatagramSize()); 70 | 71 | udpSocket->readDatagram(datagram.data(), datagram.size()); 72 | QDataStream in(&datagram, QIODevice::ReadOnly); 73 | int msgType; 74 | in >> msgType; 75 | QString usrName, ipAddr, msg; 76 | QString time = QDateTime::currentDateTime().toString("yyy-MM-dd hh:mm:ss"); 77 | 78 | switch(msgType) 79 | { 80 | case Msg: 81 | in >> usrName >> ipAddr >> msg; 82 | ui->msgBrowser->setTextColor(Qt::blue); 83 | ui->msgBrowser->setCurrentFont(QFont("Times New Roman", 12)); 84 | ui->msgBrowser->append(" [ " + usrName + " ] " + time); 85 | ui->msgBrowser->append(msg); 86 | break; 87 | case UsrEnter: 88 | in >> usrName >> ipAddr; 89 | usrEnter(usrName, ipAddr); 90 | break; 91 | case UsrLeft: 92 | in >> usrName; 93 | usrLeft(usrName, time); 94 | break; 95 | case FileName: { 96 | break; 97 | } 98 | case Refuse: 99 | break; 100 | } 101 | } 102 | } 103 | 104 | void Widget::usrEnter(QString usrname, QString ipaddr) 105 | { 106 | //判断是否已经在用户列表中 107 | bool isEmpty = ui->usrTblWidget->findItems(usrname, Qt::MatchExactly).isEmpty(); 108 | if(isEmpty) 109 | { 110 | QTableWidgetItem *usr = new QTableWidgetItem(usrname); 111 | QTableWidgetItem *ip = new QTableWidgetItem(ipaddr); 112 | ui->usrTblWidget->insertRow(0); 113 | ui->usrTblWidget->setItem(0, 0, usr); 114 | ui->usrTblWidget->setItem(0, 1, ip); 115 | ui->msgBrowser->setTextColor(Qt::gray); 116 | ui->msgBrowser->setCurrentFont(QFont("Times New Roman", 10)); 117 | ui->msgBrowser->append(tr("%1 online").arg(usrname)); 118 | ui->usrNumLbl->setText(tr("%1 online people").arg(ui->usrTblWidget->rowCount())); 119 | sndMsg(UsrEnter); 120 | } 121 | } 122 | 123 | void Widget::usrLeft(QString usrname, QString time) 124 | { 125 | int rowNum = ui->usrTblWidget->findItems(usrname, Qt::MatchExactly).first()->row(); 126 | ui->usrTblWidget->removeRow(rowNum); 127 | ui->msgBrowser->setTextColor(Qt::gray); 128 | ui->msgBrowser->setCurrentFont(QFont("Times New Roman", 10)); 129 | ui->msgBrowser->append(tr("%1 left at %2").arg(usrname).arg(time)); 130 | ui->usrNumLbl->setText(tr("%1 online people").arg(ui->usrTblWidget->rowCount())); 131 | } 132 | 133 | 134 | QString Widget::getIP() 135 | { 136 | QList list = QNetworkInterface::allAddresses(); 137 | foreach (QHostAddress addr, list) { 138 | if(addr.protocol() == QAbstractSocket::IPv4Protocol) 139 | return addr.toString(); 140 | } 141 | return 0; 142 | } 143 | 144 | QString Widget::getUsr() 145 | { 146 | return uName; 147 | } 148 | 149 | QString Widget::getMsg() 150 | { 151 | QString msg = ui->msgTxtEdit->toHtml(); 152 | ui->msgTxtEdit->clear(); 153 | ui->msgTxtEdit->setFocus(); 154 | return msg; 155 | } 156 | 157 | void Widget::on_sendBtn_clicked() 158 | { 159 | sndMsg(Msg); 160 | } 161 | 162 | void Widget::on_exitBtn_clicked() 163 | { 164 | close(); 165 | } 166 | -------------------------------------------------------------------------------- /chatRoom/widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include 5 | #include "command.h" 6 | 7 | class QUdpSocket; 8 | 9 | namespace Ui { 10 | class Widget; 11 | } 12 | 13 | class Widget : public QWidget 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit Widget(QWidget *parent, QString usrname); 19 | ~Widget(); 20 | 21 | protected: 22 | void usrEnter(QString, QString); 23 | void usrLeft(QString, QString); 24 | void sndMsg(MsgType type, QString srvaddr = ""); 25 | QString getIP(); 26 | QString getMsg(); 27 | QString getUsr(); 28 | 29 | private: 30 | Ui::Widget *ui; 31 | 32 | QUdpSocket *udpSocket; 33 | qint16 port; 34 | QString uName; 35 | 36 | private slots: 37 | void processPendingDatagrams(); 38 | void on_sendBtn_clicked(); 39 | void on_exitBtn_clicked(); 40 | }; 41 | 42 | #endif // WIDGET_H 43 | -------------------------------------------------------------------------------- /chatRoom/widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Widget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 780 10 | 450 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 5 20 | 11 21 | 541 22 | 231 23 | 24 | 25 | 26 | 27 | 28 | 29 | 3 30 | 280 31 | 541 32 | 131 33 | 34 | 35 | 36 | 37 | 38 | 39 | 555 40 | 11 41 | 221 42 | 401 43 | 44 | 45 | 46 | QAbstractItemView::SingleSelection 47 | 48 | 49 | QAbstractItemView::SelectRows 50 | 51 | 52 | 53 | 新建列 54 | 55 | 56 | 57 | 58 | ipAddress 59 | 60 | 61 | 62 | 63 | 64 | 65 | 0 66 | 250 67 | 213 68 | 22 69 | 70 | 71 | 72 | 73 | 74 | 75 | 230 76 | 250 77 | 69 78 | 22 79 | 80 | 81 | 82 | 4 83 | 84 | 85 | 86 | 8 87 | 88 | 89 | 90 | 91 | 9 92 | 93 | 94 | 95 | 96 | 10 97 | 98 | 99 | 100 | 101 | 11 102 | 103 | 104 | 105 | 106 | 12 107 | 108 | 109 | 110 | 111 | 13 112 | 113 | 114 | 115 | 116 | 14 117 | 118 | 119 | 120 | 121 | 15 122 | 123 | 124 | 125 | 126 | 16 127 | 128 | 129 | 130 | 131 | 17 132 | 133 | 134 | 135 | 136 | 18 137 | 138 | 139 | 140 | 141 | 19 142 | 143 | 144 | 145 | 146 | 20 147 | 148 | 149 | 150 | 151 | 21 152 | 153 | 154 | 155 | 156 | 22 157 | 158 | 159 | 160 | 161 | 162 | 163 | 460 164 | 420 165 | 75 166 | 23 167 | 168 | 169 | 170 | Send 171 | 172 | 173 | 174 | 175 | 176 | 560 177 | 420 178 | 75 179 | 23 180 | 181 | 182 | 183 | Exit 184 | 185 | 186 | 187 | 188 | 189 | 660 190 | 420 191 | 91 192 | 20 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /server_mysql/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ -g -Wall -std=c++11 -I /usr/include/mysql -I /usr/include/ -o main main.cpp MyReactor.cpp -pthread -lmysqlclient 3 | 4 | clean: 5 | rm -rf main 6 | -------------------------------------------------------------------------------- /server_mysql/MyReactor.cpp: -------------------------------------------------------------------------------- 1 | #include "MyReactor.h" 2 | 3 | #include "spdlog/sinks/daily_file_sink.h" 4 | #include "spdlog/sinks/basic_file_sink.h" 5 | auto my_logger = spdlog::stdout_color_mt("my_logger");//日志输出到屏幕 6 | 7 | MyReactor::MyReactor() 8 | { 9 | } 10 | 11 | MyReactor::~MyReactor() 12 | { 13 | } 14 | 15 | struct ARG//定义结构体,用于传递this指针参数 16 | { 17 | MyReactor* pThis; 18 | }; 19 | //服务器功能初始化,完成数据库的连接,服务器的初始化,accept线程、广播线程、主工作线程的创建 20 | bool MyReactor::init(const char* ip, short nport) 21 | { 22 | //连接数据库 23 | int ret = connect(); 24 | if(ret == -1) 25 | { 26 | my_logger->error("mysql connection failed"); 27 | } 28 | 29 | 30 | if(!create_server_listener(ip, nport))//create_server_listener 初始化监听请求 31 | { 32 | my_logger->error("Unable to bind: {0}:{1}.", ip, nport); 33 | return false; 34 | } 35 | 36 | ARG *arg = new ARG(); 37 | arg->pThis = this; 38 | 39 | pthread_create(&m_accept_threadid, NULL, accept_thread_proc, (void*)arg);//accept线程,接收监听请求并将请求挂到epoll监听树上 40 | 41 | pthread_create(&m_send_threadid, NULL, send_thread_proc, (void*)arg);//用于向所有连接到服务器的客户端广播消息的线程 42 | 43 | for(int i = 0; i < WORKER_THREAD_NUM; i++) 44 | { 45 | pthread_create(&m_threadid[i], NULL, worker_thread_proc, (void*)arg); 46 | } 47 | 48 | return true; 49 | } 50 | 51 | //关闭服务器 52 | bool MyReactor::uninit() 53 | { 54 | m_bStop = true; 55 | 56 | /* 将读端和写端都关闭 */ 57 | shutdown(m_listenfd, SHUT_RDWR); 58 | close(m_listenfd); 59 | close(m_epollfd); 60 | 61 | mysql_close(mysql); 62 | 63 | return true; 64 | } 65 | 66 | //epoll监听结果线程 67 | void* MyReactor::main_loop(void *p) 68 | { 69 | my_logger->info("main thread id = {}", pthread_self()); 70 | 71 | MyReactor* pReactor = static_cast(p); 72 | 73 | while(!pReactor->m_bStop) 74 | { 75 | struct epoll_event ev[1024]; 76 | int n = epoll_wait(pReactor->m_epollfd, ev, 1024, 10);//10代表阻塞等待10ms,每次循环都等待10ms,超时后直接返回0 77 | if(n == 0) 78 | continue; 79 | else if(n < 0) 80 | { 81 | my_logger->error("epoll_wait error"); 82 | continue; 83 | } 84 | 85 | int m = std::min(n, 1024); 86 | for(int i = 0; i < m; i++) 87 | { 88 | /* 有新连接 */ 89 | if(ev[i].data.fd == pReactor->m_listenfd) 90 | pthread_cond_signal(&pReactor->m_accept_cond);//唤醒accept线程 91 | /* 有数据 */ 92 | else 93 | { 94 | pthread_mutex_lock(&pReactor->m_client_mutex); 95 | pReactor->m_clientlist.push_back(ev[i].data.fd); 96 | pthread_mutex_unlock(&pReactor->m_client_mutex); 97 | pthread_cond_signal(&pReactor->m_client_cond); 98 | } 99 | } 100 | } 101 | 102 | my_logger->info("main loop exit ..."); 103 | return NULL; 104 | } 105 | 106 | //关闭客户端封装函数(将客户端的描述符从epoll的监听树上摘下,再关闭客户端的描述符) 107 | bool MyReactor::close_client(int clientfd) 108 | { 109 | if(epoll_ctl(m_epollfd, EPOLL_CTL_DEL, clientfd, NULL) == -1) 110 | { 111 | my_logger->warn("release client socket failed as call epoll_ctl fail"); 112 | } 113 | 114 | close(clientfd); 115 | return true; 116 | } 117 | 118 | //完成服务器的初始化,绑定,监听 119 | bool MyReactor::create_server_listener(const char* ip, short port) 120 | { 121 | m_listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 122 | if(m_listenfd == -1) 123 | { 124 | my_logger->error("fail to create a socket"); 125 | return false; 126 | } 127 | 128 | //设置服务器端口复用 129 | int on = 1; 130 | setsockopt(m_listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); 131 | setsockopt(m_listenfd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on)); 132 | 133 | struct sockaddr_in servaddr; 134 | memset(&servaddr, 0, sizeof(servaddr)); 135 | servaddr.sin_family = AF_INET; 136 | servaddr.sin_addr.s_addr = inet_addr(ip); 137 | servaddr.sin_port = htons(port); 138 | 139 | if(bind(m_listenfd, (sockaddr *)&servaddr, sizeof(servaddr)) == -1)//绑定服务器 140 | return false; 141 | 142 | if(listen(m_listenfd, 50) == -1)//设置监听 143 | return false; 144 | 145 | m_epollfd = epoll_create(1);//创建epoll句柄,设置监听数量 146 | if(m_epollfd == -1) 147 | return false; 148 | 149 | struct epoll_event e; 150 | memset(&e, 0, sizeof(e)); 151 | e.events = EPOLLIN | EPOLLRDHUP;//EPOLLIN: 表示对应的文件描述符可以读(包括对端SOCKET正常关闭) EPOLLHUP:表示对应的文件描述符被挂断; 152 | e.data.fd = m_listenfd; 153 | if(epoll_ctl(m_epollfd, EPOLL_CTL_ADD, m_listenfd, &e) == -1)//向监听树中添加监听描述符 154 | return false; 155 | 156 | return true; 157 | } 158 | 159 | //等待epoll监听结果,若有新的连接请求,将其设置为非阻塞模式,并添加到epoll的监听树上 160 | void* MyReactor::accept_thread_proc(void* args) 161 | { 162 | ARG *arg = (ARG*)args; 163 | MyReactor* pReactor = arg->pThis;//获取this指针 164 | 165 | while(!pReactor->m_bStop) 166 | { 167 | pthread_mutex_lock(&pReactor->m_accept_mutex);//加锁 168 | pthread_cond_wait(&pReactor->m_accept_cond, &pReactor->m_accept_mutex); 169 | //阻塞等待条件变量m_accept_cond,同时释放互斥锁m_accept_mutex 170 | //当条件变量满足,线程被唤醒,同时重新加锁 171 | 172 | struct sockaddr_in clientaddr; 173 | socklen_t addrlen; 174 | int newfd = accept(pReactor->m_listenfd, (struct sockaddr *)&clientaddr, &addrlen); 175 | pthread_mutex_unlock(&pReactor->m_accept_mutex); 176 | if(newfd == -1) 177 | continue; 178 | 179 | 180 | pthread_mutex_lock(&pReactor->m_cli_mutex); 181 | pReactor->m_fds.insert(newfd); 182 | pthread_mutex_unlock(&pReactor->m_cli_mutex); 183 | 184 | my_logger->info("new client connected:"); 185 | std::cout<error("fcntl error, oldflag = {0}, newflag = {1}", oldflag, newflag); 193 | continue; 194 | } 195 | 196 | struct epoll_event e; 197 | memset(&e, 0, sizeof(e)); 198 | e.events = EPOLLIN | EPOLLRDHUP | EPOLLET;//EPOLLET epoll以水平触发模式工作,配合O_NONBLOCK使用,高效 199 | e.data.fd = newfd; 200 | /* 添加进epoll的兴趣列表 */ 201 | if(epoll_ctl(pReactor->m_epollfd, EPOLL_CTL_ADD, newfd, &e) == -1) 202 | { 203 | my_logger->error("epoll_ctl error, fd = {}", newfd); 204 | } 205 | } 206 | 207 | return NULL; 208 | } 209 | 210 | //接收客户端消息,并完成用户数据与数据库的连接,对用户信息直接发送给客户端(不广播),对用户消息封装后交给广播线程 211 | void* MyReactor::worker_thread_proc(void* args) 212 | { 213 | ARG *arg = (ARG*)args; 214 | MyReactor* pReactor = arg->pThis; 215 | 216 | while(!pReactor->m_bStop) 217 | { 218 | int clientfd; 219 | pthread_mutex_lock(&pReactor->m_client_mutex); 220 | /* 注意!要用while循环等待 */ 221 | while(pReactor->m_clientlist.empty()) 222 | pthread_cond_wait(&pReactor->m_client_cond, &pReactor->m_client_mutex); 223 | 224 | /* 取出客户套接字 */ 225 | clientfd = pReactor->m_clientlist.front(); 226 | pReactor->m_clientlist.pop_front(); 227 | pthread_mutex_unlock(&pReactor->m_client_mutex); 228 | 229 | 230 | //std::cout <<"run1..."<error("recv error, client disconnected, fd = {}", clientfd); 254 | pReactor->close_client(clientfd); 255 | bError = true; 256 | break; 257 | } 258 | } 259 | /* 对端关闭了socket,这端i也关闭 */ 260 | else if(nRecv == 0) 261 | { 262 | /* 将该客户从accept后的客户列表中删除(从epoll的监听树上删除) */ 263 | pthread_mutex_lock(&pReactor->m_cli_mutex); 264 | pReactor->m_fds.erase(clientfd); 265 | pthread_mutex_unlock(&pReactor->m_cli_mutex); 266 | char query[100]; 267 | int ret; 268 | pthread_mutex_lock(&pReactor->m_clie_name); 269 | std::cout<<"this clientfd:"<sqlQuery(query); 272 | if(ret==-1) 273 | { 274 | my_logger->error("select clientfd error:{}",mysql_error(pReactor->mysql)); 275 | } 276 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 277 | char name[20]; 278 | std::string tempstr; 279 | if(!pReactor->m_clientname.empty()) 280 | { 281 | while((pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr))) 282 | { 283 | //std::cout<<"search name:"<sqlrow[0]<::iterator it; 285 | for(it=pReactor->m_clientname.begin(); 286 | it!=pReactor->m_clientname.end();it++) 287 | { 288 | //std::cout<<"*it:"<<*it<sqlrow[0]) 290 | { 291 | tempstr=*it; 292 | strcpy(name,(*it).c_str()); 293 | std::cout<<"username:"<res_ptr); 296 | sprintf(query,"select online from UserInfo where username='%s'",name); 297 | ret=pReactor->sqlQuery(query); 298 | if(ret==-1) 299 | { 300 | my_logger->error("select online error:{}",mysql_error(pReactor->mysql)); 301 | } 302 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 303 | pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr); 304 | if(atoi(pReactor->sqlrow[0])==1) 305 | { 306 | memset(query,0,sizeof(query)); 307 | sprintf(query,"update UserInfo set online=%d where username='%s'",0,name); 308 | int ret=pReactor->sqlQuery(query); 309 | if(ret==-1) 310 | { 311 | my_logger->error("update online error:{}",mysql_error(pReactor->mysql)); 312 | } 313 | pReactor->m_clientname.remove(tempstr); 314 | tempstr.clear(); 315 | break; 316 | } 317 | } 318 | } 319 | } 320 | } 321 | mysql_free_result(pReactor->res_ptr); 322 | my_logger->info("peer closed, client disconnected, fd = {}", clientfd); 323 | pReactor->close_client(clientfd); 324 | //std::cout<<"close over"<m_clie_name); 327 | break; 328 | } 329 | 330 | //注册 331 | if(buff[0] == REGISTER) 332 | { 333 | //std::cout<<"buff:"<mysql)); 361 | strclientmsg += "The name has been registered"; 362 | } 363 | else 364 | { 365 | memset(query, 0, sizeof(query)); 366 | //std::cout<<"clientfd: "<sqlQuery(query); 370 | if(ret == -1) 371 | { 372 | my_logger->error("insert error {}", mysql_error(pReactor->mysql)); 373 | } 374 | else 375 | { 376 | //注册成功 377 | //新建一个用户表,用于保存用户信息 378 | memset(query, 0, sizeof(query)); 379 | sprintf(query, "create table %s (friends char(30));",name); 380 | //std::cout<<"query3: "<sqlQuery(query); 382 | if(ret==-1) 383 | { 384 | my_logger->error("create table error:{}",mysql_error(pReactor->mysql)); 385 | } 386 | //把自己加入到好友表中 387 | memset(query, 0, sizeof(query)); 388 | sprintf(query, "insert into %s values('%s')", name, name); 389 | ret=pReactor->sqlQuery(query); 390 | if(ret==-1) 391 | { 392 | my_logger->error("inserr error:{}",mysql_error(pReactor->mysql)); 393 | } 394 | strclientmsg += "REGISTER SUCCESS"; 395 | // continue; 396 | if(mysql_errno(pReactor->mysql)) 397 | { 398 | my_logger->error("retrive error {}", mysql_error(pReactor->mysql)); 399 | } 400 | } 401 | } 402 | mysql_free_result(pReactor->res_ptr); 403 | } 404 | //登录 405 | else if(buff[0] == LOGIN) 406 | { 407 | std::string rec(buff); 408 | auto it = rec.find('\t'); 409 | char name[20]; 410 | strcpy(name,rec.substr(1,it-1).c_str()); 411 | std::string str(name); 412 | char password[30]; 413 | strcpy(password,rec.substr(it+1, rec.size()-1).c_str()); 414 | 415 | char query[100]; 416 | sprintf(query, "select password from UserInfo where username = '%s'",name); 417 | pReactor->sqlQuery(query); 418 | /* std::cout << "ret = " << ret << std::endl; */ 419 | pReactor->res_ptr = mysql_store_result(pReactor->mysql); 420 | pReactor->sqlrow = mysql_fetch_row(pReactor->res_ptr); 421 | if(!pReactor->sqlrow) 422 | { 423 | strclientmsg += "You have to register first"; 424 | //my_logger->error("select error {}", mysql_error(pReactor->mysql)); 425 | } 426 | else 427 | { 428 | int ret; 429 | if(strcmp(pReactor->sqlrow[0], password) == 0) 430 | { 431 | pReactor->m_clientname.push_back(str); 432 | strclientmsg += "LOG IN SUCCESS"; 433 | std::cout<res_ptr); 437 | memset(query, 0, sizeof(query)); 438 | sprintf(query,"select clientfd from UserInfo where username='%s'",name); 439 | ret=pReactor->sqlQuery(query); 440 | if(ret == -1) 441 | { 442 | my_logger->error("select error {}", mysql_error(pReactor->mysql)); 443 | } 444 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 445 | pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr); 446 | if(clientfd!=atoi(pReactor->sqlrow[0])) 447 | { 448 | memset(query, 0, sizeof(query)); 449 | sprintf(query,"update UserInfo set clientfd=%d where username='%s'",clientfd,name); 450 | ret=pReactor->sqlQuery(query); 451 | if(ret == -1) 452 | { 453 | my_logger->error("update error {}", mysql_error(pReactor->mysql)); 454 | } 455 | my_logger->info("server msg:{} have changed client to LOGIN",name); 456 | } 457 | memset(query,0,sizeof(query)); 458 | sprintf(query,"update UserInfo set online=%d where username='%s'",1,name); 459 | pReactor->sqlQuery(query); 460 | } 461 | else 462 | { 463 | strclientmsg += "password is wrong"; 464 | } 465 | //continue; 466 | if(mysql_errno(pReactor->mysql)) 467 | { 468 | my_logger->error("Retrive error {}", mysql_error(pReactor->mysql)); 469 | } 470 | 471 | } 472 | mysql_free_result(pReactor->res_ptr); 473 | } 474 | else if(buff[0]==FRIENDSLIST) 475 | { 476 | char query[100]; 477 | char name[20]; 478 | std::string rec(buff); 479 | strcpy(name,rec.substr(1,rec.size()-1).c_str()); 480 | //std::cout<<"FRIENDLIST name:"<sqlQuery(query); 484 | if(ret==-1) 485 | { 486 | my_logger->error("select friends error:{}",mysql_error(pReactor->mysql)); 487 | } 488 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 489 | int rows=(int)mysql_num_fields(pReactor->res_ptr); 490 | //std::cout<<"clientfd:"< friendsmsg; 492 | std::string friendsmsg; 493 | int count=0; 494 | std::string tempstr; 495 | while((pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr))) 496 | { 497 | int i; 498 | for(i=0;isqlrow[i]; 501 | friendsmsg+=":"; 502 | //std::cout<<"friendsmsg:"<res_ptr); 515 | 516 | } 517 | //ONLINESTATE 518 | else if(buff[0]==ONLINESTATE) 519 | { 520 | //pReactor->onlineState_fd=clientfd; 521 | char query[100]; 522 | sprintf(query,"select username,online,pic from UserInfo"); 523 | pReactor->sqlQuery(query); 524 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 525 | int count=0; 526 | std::string namemsg; 527 | std::string onlinemsg; 528 | std::string picmsg; 529 | std::string allmsg; 530 | std::string tempstr; 531 | while((pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr))) 532 | { 533 | namemsg+=pReactor->sqlrow[0]; 534 | onlinemsg+=pReactor->sqlrow[1]; 535 | picmsg+=pReactor->sqlrow[2]; 536 | allmsg+=namemsg+","+onlinemsg+","+picmsg+",:"; 537 | tempstr+=allmsg; 538 | //send(clientfd,allmsg.c_str(),allmsg.size(),0); 539 | namemsg.clear(); 540 | onlinemsg.clear(); 541 | picmsg.clear(); 542 | allmsg.clear(); 543 | count++; 544 | } 545 | char str[5]; 546 | sprintf(str,"%d",count); 547 | tempstr+=str; 548 | //std::cout<<"ONLINESTATE tempstr--"<res_ptr); 551 | } 552 | else if(buff[0]==PICCHANGE) 553 | { 554 | std::string rec(buff); 555 | auto it=rec.find(':'); 556 | char name[20]; 557 | int pic,ret; 558 | char query[100]; 559 | strcpy(name,rec.substr(1,it-1).c_str()); 560 | std::cout<<"name "<sqlQuery(query); 565 | if(ret==-1) 566 | { 567 | my_logger->error("update pic error:{}",mysql_error(pReactor->mysql)); 568 | } 569 | } 570 | //聊天信息 571 | else if(buff[0] == MESSAGE) 572 | { 573 | strclientmsg += buff; 574 | } 575 | // TODO:添加好友消息 576 | else if(buff[0] == ADDFRIEND) 577 | { 578 | std::string rec(buff); 579 | char query[100]; 580 | char fromname[20],toname[20]; 581 | auto it=rec.find('+'); 582 | strcpy(fromname,rec.substr(1,it-1).c_str()); 583 | strcpy(toname,rec.substr(it+1,rec.size()-1).c_str()); 584 | sprintf(query,"select username from UserInfo where username='%s'",toname); 585 | pReactor->sqlQuery(query); 586 | pReactor->res_ptr = mysql_store_result(pReactor->mysql); 587 | pReactor->sqlrow = mysql_fetch_row(pReactor->res_ptr); 588 | mysql_free_result(pReactor->res_ptr); 589 | if(!pReactor->sqlrow) 590 | { 591 | strclientmsg+="The name is wrong"; 592 | } 593 | else 594 | { 595 | memset(query,0,sizeof(query)); 596 | sprintf(query,"select friends from %s where friends='%s'",fromname,toname); 597 | pReactor->sqlQuery(query); 598 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 599 | pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr); 600 | mysql_free_result(pReactor->res_ptr); 601 | if(pReactor->sqlrow) 602 | { 603 | strclientmsg+="you are have been friends!"; 604 | } 605 | else 606 | { 607 | memset(query,0,sizeof(query)); 608 | sprintf(query,"select clientfd from UserInfo where username='%s'",toname); 609 | pReactor->sqlQuery(query); 610 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 611 | pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr); 612 | int tg_clientfd=atoi(pReactor->sqlrow[0]); 613 | std::cout<<"tg_clientfd: "<sqlQuery(query1); 646 | ret=pReactor->sqlQuery(query2); 647 | pReactor->sqlQuery(query); 648 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 649 | pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr); 650 | int tg_clientfd=atoi(pReactor->sqlrow[0]); 651 | if(ret == -1) 652 | { 653 | my_logger->error("insert error {}", mysql_error(pReactor->mysql)); 654 | } 655 | std::string str="*ACCEPT."; 656 | send(tg_clientfd,str.c_str(),str.size(),0); 657 | strclientmsg+=buff; 658 | } 659 | else if(buff[0]==REFUSE) 660 | { 661 | std::string rec(buff); 662 | char fromname[20]; 663 | char query[100]; 664 | int ret; 665 | strcpy(fromname,rec.substr(1,rec.size()-1).c_str()); 666 | sprintf(query,"select clientfd from UserInfo where username='%s'",fromname); 667 | ret=pReactor->sqlQuery(query); 668 | if(ret==-1) 669 | { 670 | my_logger->error("select error {}",mysql_error(pReactor->mysql)); 671 | } 672 | pReactor->res_ptr=mysql_store_result(pReactor->mysql); 673 | pReactor->sqlrow=mysql_fetch_row(pReactor->res_ptr); 674 | if(!pReactor->sqlrow) 675 | { 676 | my_logger->info("server msg:there is no user called {} in database UserInfo",fromname); 677 | } 678 | int tg_clientfd=atoi(pReactor->sqlrow[0]); 679 | std::string msg="your requet had been refused..."; 680 | send(tg_clientfd,msg.c_str(),msg.size(),0); 681 | } 682 | else 683 | { 684 | strclientmsg+=buff; 685 | } 686 | } 687 | //std::cout<<"run3..."<info("client msg: {}", strclientmsg.substr(1,strclientmsg.size()-1)); 696 | } 697 | else 698 | { 699 | if(strclientmsg!="") 700 | { 701 | my_logger->info("client msg: {}", strclientmsg); 702 | } 703 | } 704 | 705 | if(strclientmsg[0] == MESSAGE||strclientmsg[0] == ACCEPT) 706 | { 707 | strclientmsg.erase(0, 1); //将命令标识符去掉 708 | /* 将消息加上时间戳 */ 709 | ostimestr << "[" << nowstr->tm_year + 1900 << "-" 710 | << std::setw(2) << std::setfill('0') << nowstr->tm_mon + 1 << "-" 711 | << std::setw(2) << std::setfill('0') << nowstr->tm_mday << " " 712 | << std::setw(2) << std::setfill('0') << nowstr->tm_hour << ":" 713 | << std::setw(2) << std::setfill('0') << nowstr->tm_min << ":" 714 | << std::setw(2) << std::setfill('0') << nowstr->tm_sec << " ] "; 715 | 716 | strclientmsg.insert(0, ostimestr.str());//将时间戳插入到消息字符串的前面 717 | } 718 | else//不是交流的消息(注册、登录信息),就直接单独发送给客户端,不用广播 719 | { 720 | if(strclientmsg!="") 721 | { 722 | send(clientfd, strclientmsg.c_str(), strclientmsg.length(), 0); 723 | } 724 | continue;//阶数本次循环,不会再广播 725 | } 726 | 727 | /* 将消息交给发送广播消息的线程 */ 728 | pReactor->m_msgs.push_back(strclientmsg); 729 | pthread_cond_signal(&pReactor->m_send_cond); 730 | //std::cout<<"run4..."<pThis; 740 | 741 | while(!pReactor->m_bStop) 742 | { 743 | std::string strclientmsg; 744 | 745 | pthread_mutex_lock(&pReactor->m_send_mutex); 746 | /* 注意!要用while循环等待 */ 747 | while(pReactor->m_msgs.empty()) 748 | pthread_cond_wait(&pReactor->m_send_cond, &pReactor->m_send_mutex);//线程阻塞在条件变量上等待 749 | 750 | //线程被唤醒,取出列首数据,并将列首弹出 751 | strclientmsg = pReactor->m_msgs.front(); 752 | pReactor->m_msgs.pop_front(); 753 | pthread_mutex_unlock(&pReactor->m_send_mutex); 754 | 755 | std::cout << std::endl; 756 | 757 | 758 | while(1) 759 | { 760 | int nSend; 761 | int clientfd; 762 | //广播消息(向所有与服务器建立连接的客户端发送消息) 763 | for(auto it = pReactor->m_fds.begin(); it != pReactor->m_fds.end(); it++) 764 | { 765 | clientfd = *it; 766 | //std::cout<<"------onlineState_fd-----"<onlineState_fd<onlineState_fd) 768 | // continue; 769 | nSend = send(clientfd, strclientmsg.c_str(), strclientmsg.length(), 0); 770 | if(nSend == -1) 771 | { 772 | if(errno == EWOULDBLOCK) 773 | { 774 | sleep(10); 775 | continue; 776 | } 777 | else 778 | { 779 | my_logger->error("send error, fd = {}", clientfd); 780 | pReactor->close_client(clientfd); 781 | break; 782 | } 783 | } 784 | } 785 | 786 | my_logger->info("send: {}", strclientmsg); 787 | /* 发送完把缓冲区清干净 */ 788 | strclientmsg.clear(); 789 | 790 | //代表整个while循环只执行一次 791 | if(strclientmsg.empty()) 792 | break; 793 | } 794 | } 795 | 796 | return NULL; 797 | } 798 | 799 | //数据库连接 800 | int MyReactor::connect() 801 | { 802 | mysql = mysql_init(NULL);//数据库初始化 803 | if(!mysql) 804 | { 805 | my_logger->error("mysql init falied"); 806 | return -1; 807 | } 808 | 809 | /* root为用户名,mysql123为密码,ChatRoom为要连接的database */ 810 | mysql = mysql_real_connect(mysql, IP, "root", "mysql123", "ChatRoom", 0, NULL, 0);//连接到数据库 811 | 812 | if(mysql) 813 | { 814 | my_logger->info("MySQL connection success"); 815 | } 816 | else 817 | { 818 | my_logger->warn(" MySQL connection failed"); 819 | } 820 | return 0; 821 | } 822 | 823 | //数据库操作 824 | int MyReactor::sqlQuery(const char* query) 825 | { 826 | int res = mysql_query(mysql, query); 827 | //std::cout<<"query res= "< 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include //for htonl() and htons() 11 | #include 12 | #include 13 | #include 14 | #include //for signal() 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include //for std::setw()/setfill() 25 | #include 26 | 27 | #include 28 | 29 | #include 30 | #include "spdlog/spdlog.h" 31 | #include "spdlog/sinks/stdout_color_sinks.h" 32 | 33 | #include "command.h" 34 | 35 | #include 36 | 37 | #define WORKER_THREAD_NUM 5 38 | 39 | 40 | class MyReactor{ 41 | public: 42 | MyReactor(); 43 | ~MyReactor(); 44 | 45 | /* 初始化socket和线程,供应用程序调用 */ 46 | bool init(const char *ip, short nport); 47 | 48 | bool uninit(); 49 | 50 | bool close_client(int clientfd);//关闭客户端 51 | 52 | static void* main_loop(void* loop); 53 | 54 | //数据库操作 55 | int connect(); 56 | int sqlQuery(const char*); 57 | 58 | private: 59 | /* 见条款6,阻止有人调用复制构造函数和赋值运算符构造函数 */ 60 | MyReactor(const MyReactor& rhs); 61 | MyReactor& operator = (const MyReactor& rhs); 62 | 63 | static void *accept_thread_proc(void* args);//接收信息线程工作函数 64 | static void *worker_thread_proc(void* args);// 65 | 66 | static void *send_thread_proc(void* args);//发送信息线程工作函数 67 | 68 | bool create_server_listener(const char* ip, short port); 69 | 70 | 71 | private: 72 | /* 服务器端的socket */ 73 | int m_listenfd = 0; 74 | /* 让线程可以修改它 */ 75 | int m_epollfd = 0; 76 | /* 线程ID */ 77 | pthread_t m_accept_threadid;//接收信息线程Pid 78 | pthread_t m_threadid[WORKER_THREAD_NUM];//工作线程pid[] 79 | 80 | pthread_t m_send_threadid;//发送广播的线程pid 81 | 82 | //静态初始化线程锁 83 | /* 接受客户的信号量 */ 84 | pthread_mutex_t m_accept_mutex = PTHREAD_MUTEX_INITIALIZER; 85 | /* 有新连接的条件变量 */ 86 | pthread_cond_t m_accept_cond = PTHREAD_COND_INITIALIZER; 87 | /* 添加、取出客户链表的信号量 */ 88 | pthread_mutex_t m_client_mutex = PTHREAD_MUTEX_INITIALIZER; 89 | /* 通知工作线程有客户消息的条件变量 */ 90 | pthread_cond_t m_client_cond = PTHREAD_COND_INITIALIZER; 91 | 92 | pthread_mutex_t m_send_mutex = PTHREAD_MUTEX_INITIALIZER;//发送信息的线程锁 93 | pthread_cond_t m_send_cond = PTHREAD_COND_INITIALIZER; 94 | std::deque m_msgs; 95 | 96 | pthread_mutex_t m_cli_mutex = PTHREAD_MUTEX_INITIALIZER;//添加accept后的文件描述符的互斥锁 97 | pthread_cond_t m_cli_cond = PTHREAD_COND_INITIALIZER; 98 | 99 | std::set m_fds;//存放accept后的文件描述符 100 | 101 | /* 存储连接客户的链表,用队列也一样*/ 102 | std::list m_clientlist; 103 | pthread_mutex_t m_clie_name=PTHREAD_MUTEX_INITIALIZER; 104 | std::list m_clientname; 105 | int onlineState_fd=0; 106 | 107 | /* 决定主线程、accept线程、工作线程是否继续迭代 */ 108 | bool m_bStop = false;//false代表迭代(一直进行下去) 109 | 110 | /* MySQL数据库 */ 111 | MYSQL *mysql; 112 | MYSQL_RES *res_ptr; 113 | MYSQL_ROW sqlrow; 114 | }; 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /server_mysql/command.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMAND_H 2 | #define COMMAND_H 3 | 4 | #define IP "122.51.90.199" 5 | #define REGISTER '1' 6 | #define LOGIN '2' 7 | #define MESSAGE '3' 8 | #define ADDFRIEND '4' 9 | #define ADDREQUEST '5' 10 | #define ACCEPT '6' 11 | #define REFUSE '7' 12 | #define FRIENDSLIST '8' 13 | #define ONLINE '9' 14 | #define ONLINESTATE 'o' 15 | #define PICCHANGE 'p' 16 | #endif // COMMAND_H 17 | -------------------------------------------------------------------------------- /server_mysql/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/server_mysql/main -------------------------------------------------------------------------------- /server_mysql/main.cpp: -------------------------------------------------------------------------------- 1 | #include "MyReactor.h" 2 | 3 | 4 | #include "spdlog/sinks/daily_file_sink.h" 5 | #include "spdlog/sinks/basic_file_sink.h" 6 | auto main_logger = spdlog::stdout_color_mt("main_logger"); 7 | 8 | 9 | MyReactor g_reactor; 10 | 11 | 12 | void prog_exit(int signo) 13 | { 14 | main_logger->info("program recv signal {} to exit.", signo); 15 | g_reactor.uninit();//关闭服务器 16 | } 17 | 18 | void daemon_run() 19 | { 20 | int pid; 21 | signal(SIGCHLD, SIG_IGN); 22 | pid = fork(); 23 | if (pid < 0) 24 | { 25 | main_logger->error("fork error"); 26 | exit(-1); 27 | } 28 | else if (pid > 0) { 29 | exit(0); 30 | } 31 | //之前parent和child运行在同一个session里,parent是会话(session)的领头进程, 32 | //parent进程作为会话的领头进程,如果exit结束执行的话,那么子进程会成为孤儿进程,并被init收养。 33 | //执行setsid()之后,child将重新获得一个新的会话(session)id。 34 | //这时parent退出之后,将不会影响到child了。 35 | setsid(); 36 | int fd; 37 | fd = open("/dev/null", O_RDWR, 0); 38 | if (fd != -1) 39 | { 40 | dup2(fd, STDIN_FILENO); 41 | dup2(fd, STDOUT_FILENO); 42 | dup2(fd, STDERR_FILENO); 43 | } 44 | if (fd > 2) 45 | close(fd); 46 | } 47 | 48 | 49 | int main(int argc, char* argv[]) 50 | { 51 | //设置信号处理 52 | signal(SIGCHLD, SIG_DFL); 53 | signal(SIGPIPE, SIG_IGN); 54 | signal(SIGINT, prog_exit); 55 | signal(SIGKILL, prog_exit); 56 | signal(SIGTERM, prog_exit); 57 | 58 | short port = 0; 59 | int ch; 60 | bool bdaemon = false; 61 | while ((ch = getopt(argc, argv, "p:d")) != -1) 62 | { 63 | switch (ch) 64 | { 65 | case 'd': 66 | bdaemon = true; 67 | break; 68 | case 'p': 69 | port = atol(optarg); 70 | break; 71 | } 72 | } 73 | 74 | if (bdaemon) 75 | daemon_run(); 76 | 77 | 78 | if (port == 0) 79 | port = 12345; 80 | 81 | if (!g_reactor.init("0.0.0.0", 12345)) 82 | return -1; 83 | 84 | 85 | g_reactor.main_loop(&g_reactor); 86 | 87 | main_logger->info("main exit"); 88 | 89 | return 0; 90 | } 91 | 92 | 93 | -------------------------------------------------------------------------------- /spdlog-1.x.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CXHGT/TCP-ChatRoom/99790ff02ae5bb040e525390561b8d769ec9415b/spdlog-1.x.zip --------------------------------------------------------------------------------