密码传情
任务描述:
一、 题目
在互联网上,曾经出现了一个感人的密码传情事件。一位网友收到了心仪的女生给他的答复,用摩尔斯密码表示如下:
****-/*----/----*/****-/****-/*----/---**/*----/****-/*----/-****/***--/****-/*----/----*/**---/-****/**---/**---/***--/--***/****-/
经过热心网友们的协助,破解了这段有5次编码组成的密码。过程如下:
a、摩尔斯解码:
得到:4194418141634192622374
b、手机按键码表:
得到:G Z G T G O G X N C S
c、QWE键盘码表:
得到:O T O E O I O U Y V L
d、栅栏密码:(两排栅栏)
得到:O O T U O Y E V O L I
e、倒序排列:
得到:I L O V E Y O U T O O (最终结果)
请利用这几种密码机制,编写一款聊天工具。
二、 初赛阶段要求
1. 聊天工具由客户端与服务器端组成。所有客户端之间的聊天内容,都通过服务器端进行转发,不进行客户端之间的点对点直接通信;
2. 客户端与服务器端可以为不同机器,也可以为机器上的不同窗口。二者之间用socket进行通信;
3. 服务器端管理的用户信息包括:(用户信息不用加密发送)
1) 用户名称(可含中文,最大16字符)
2) 用户ID(10位数字)
3) 密码(10位数字)
4. 用户的基本信息可在服务器端进行添加/删除/修改/查询。用户密码可以在客户端登录后修改;
5. 服务器端与客户端均可从PC机的当前IP地址组中选取一个IP地址使用。同时,启用的socket端口号可以指定;可以查看并修改当前的IP地址、socket端口号;
6. 客户端输入服务器端的IP地址和socket端口号,并通过用户ID和密码验证后,进入工作状态。发送信息时,需要指定接收用户的ID;
7. 当相同用户尝试在多个终端登录时,旧的终端告警并断开连接,新的终端启用;
8. 服务器端限定10个用户同时处于连接使用状态;
9. 客户端可以设置个人的密码策略。利用该策略,可以设置信息加密时每一步编码的算法,如策略 edcdcba则表示编码顺序为:倒序、栅栏、QWE、栅栏、QWE、手机、摩尔斯。(最后两步必须为手机编码和摩尔斯编码)(注意:设计中需要分析策略中各种编码方法的约束条件。最大策略设计为不超过8次编码)(新用户默认编码策略为空,采用未加密的明码发送信息)
10. 信息发送时只需要指定接收方的ID即可,不用知道接收方的密码策略;
11. 最后输出的摩尔斯码流将转换成二进制流方式发送,用1表示“-”,0表示“*”;
12. 客户端包含图形界面与命令行两种工作方式;
13. 编码与解码的每一步结果,将可以调试输出;
14. 初赛只处理纯字母字符串,字母统一转换为小写处理。对非字母以外的字符有检查与提示;
15. 输入单行字母串后,回车进行发送;
16. 附:数字的摩尔斯码表:
0:― ― ― ― ― 1:* ― ― ― ― 2:* * ― ― ― 3:* * * ― ―
4:* * * * ― 5:* * * * * 6:― * * * * 7:― ― * * *
8:― ― ― * * 9:――――*
三、 初赛阶段说明
1. 限用C、C++语言编码,不使用Java 或脚本语言;
2. 概念层次清晰,程序结构合理;
3. 提供程序框架设计文档、关键算法流程设计文档;
4. 提供使用手册,包含主要工作界面截图;
5. 提供源码包(含工程编译配置)与可执行程序(静态链接);
6. 手机按键编码:传统的电话/手机,会复用’2’--‘9’的八个数字键盘,进行英文字母的输入。如数字’3’,可输入’d’’e’’f’三个字母。按数字’2’键两次,表示字母’e’,用编码3 2描述。完整码表请查看手机;
7. QWE键盘编码:按照电脑英文键盘的格式进行编码,即1:Q、2:W、3:E 。。。,转换成字母替换,则为:a:Q、b:W、c:E 。。。,完整码表请查看电脑键盘;
8. 栅栏编码:将字串按间隔N拆成N排,然后重新组合。如字串abcdef,用2排栅栏编码后变成acebdf,用3排栅栏编码后变成adbecf;
9. 演示用字符串:“ZhongXingPengYue”;
四、 系统实现技术提示信息
1. 关注时间与空间性能
2. 容错能力
五、 审核标准及评价细则(初赛阶段满分100分)
功能完备,清晰易用;
程序可运行,无明显故障;
代码规范,结构合理;
设计完善,文档齐全;
有性能、容错、调测等方面分析与处理;
服务器端:
debug.h
1/**//*
2debug.h
3调试开关,决定是否启用调试功能
4由宏 DEBUG 是否定义决定是否启动调试功能
5*/
6
7
8#ifndef __DEBUG_H_INCLUDED__
9#define __DEBUG_H_INCLUDED__
10
11
12#ifndef DEBUG
13// #define DEBUG
14#endif
15
16
17#endif // __DEBUG_H_INCLUDED__
18
doubleLove.h
1/**//*
2doubleLove.h
3包含必要头文件,定义数据类型和一些常量
4*/
5
6
7#ifndef __DOUBLELOVE_H_INCLUDED__
8#define __DOUBLELOVE_H_INCLUDED__
9
10
11 // 确保 UNICODE 编码
12#ifndef UNICODE
13#define UNICODE
14#endif
15
16#ifndef _UNICODE
17#define _UNICODE
18#endif
19
20#include <WinSock2.h>
21#include <WS2tcpip.h>
22#include <Windows.h>
23
24
25#include "debug.h"
26
27
28typedef unsigned char U08;
29typedef unsigned short U16;
30typedef unsigned int U32;
31#define U32_MAX 0xFFFFFFFF
32
33typedef char I08;
34typedef short I16;
35typedef int I32;
36
37typedef char C08;
38typedef C08 *Sz08;
39typedef const C08 * cSz08;
40typedef C08 *Pc08;
41typedef const C08 * cPc08;
42
43typedef wchar_t C16;
44typedef C16 *Sz16;
45typedef const C16 * cSz16;
46typedef C16 *Pc16;
47typedef const C16 * cPc16;
48
49#define T16(x) L##x
50#define T08(x) x
51
52typedef bool B32;
53#define BTRUE true
54#define BFALSE false
55
56 // 函数返回状态
57typedef U32 R32;
58 // 正常返回
59#define ROK 0
60 // 出错返回
61#define RERR 1
62
63
64#endif // __DOUBLELOVE_H_INCLUDED__
65
packet.cpp
1/**//*
2packet.cpp
3实现 CPacket
4通信数据包及辅助功能
5*/
6
7
8#include "packet.h"
9#include "toolSz.h"
10
11
12CPacket::CPacket() {
13 ::InitializeCriticalSection( &(this->csAll) );
14 this->bRight = BFALSE;
15 this->len = 0;
16}
17
18CPacket::~CPacket() {
19 ::DeleteCriticalSection( &(this->csAll) );
20}
21
22R32 CPacket::recv( SOCKET s ) {
23 R32 res = RERR;
24 U32 bodyLen;
25 ::EnterCriticalSection( &(this->csAll) );
26 this->bRight = BFALSE;
27 res = CPacket::recvFull( s, PACKET_HEADER_LEN, this->buffer );
28 if ( res == ROK ) {
29 CPacket::getU32fromNetU08( bodyLen, this->buffer + USER_ID_LEN+USER_ID_LEN+4 );
30 if ( bodyLen <= PACKET_BODY_LEN_MAX ) {
31 // if bodyLen == 0 then return ROK
32 res = CPacket::recvFull( s, bodyLen, this->buffer + PACKET_HEADER_LEN );
33 if ( res == ROK ) {
34 this->len = bodyLen + PACKET_HEADER_LEN;
35 this->bRight = BTRUE;
36 }
37 }
38 }
39 ::LeaveCriticalSection( &(this->csAll) );
40 return res;
41}
42
43R32 CPacket::send( SOCKET s ) const {
44 R32 res = RERR;
45 ::EnterCriticalSection( &(this->csAll) );
46 if ( this->bRight ) {
47 res = CPacket::sendFull( s, this->len, this->buffer );
48 }
49 ::LeaveCriticalSection( &(this->csAll) );
50 return res;
51}
52
53R32 CPacket::parse( CUserId *pIdDest, CUserId *pIdSrc, U32 *pCmd, U32 *pLen, U08 *body, U32 maxBodyLen, U08 *header ) const {
54 R32 res = RERR;
55 U32 bodyLen;
56 ::EnterCriticalSection( &(this->csAll) );
57 if ( this->bRight ) {
58 res = ROK;
59 if ( pIdDest != NULL ) {
60 *pIdDest = this->buffer;
61 }
62 if( pIdSrc != NULL ) {
63 *pIdSrc = ( this->buffer + USER_ID_LEN );
64 }
65 if ( pCmd != NULL ) {
66 CPacket::getU32fromNetU08( *pCmd, this->buffer+USER_ID_LEN+USER_ID_LEN );
67 }
68 CPacket::getU32fromNetU08( bodyLen, this->buffer+USER_ID_LEN+USER_ID_LEN+4 );
69 if ( pLen != NULL ) {
70 *pLen = bodyLen;
71 }
72 if ( body != NULL ) {
73 if ( bodyLen <= maxBodyLen ) {
74 ::copyArray( body, this->buffer + PACKET_HEADER_LEN, bodyLen );
75 }
76 else {
77 res = RERR;
78 }
79 }
80 if ( header != NULL ) {
81 ::copyArray( header, this->buffer, PACKET_HEADER_LEN );
82 }
83 }
84 ::LeaveCriticalSection( &(this->csAll) );
85 return res;
86}
87
88R32 CPacket::build( const CUserId &idDest, const CUserId &idSrc, U32 cmd, U32 bodyLen, const U08 *body ) {
89 if ( (bodyLen>0) && (body==NULL) ) {
90 return RERR;
91 }
92 if ( bodyLen > PACKET_BODY_LEN_MAX ) {
93 return RERR;
94 }
95 ::EnterCriticalSection( &(this->csAll) );
96 this->bRight = BFALSE;
97 idDest.getU08( this->buffer );
98 idSrc.getU08( this->buffer + USER_ID_LEN );
99 CPacket::getNetU08fromU32( this->buffer + USER_ID_LEN + USER_ID_LEN, cmd );
100 CPacket::getNetU08fromU32( this->buffer + USER_ID_LEN + USER_ID_LEN + 4, bodyLen );
101 if ( bodyLen > 0 ) {
102 ::copyArray( this->buffer + PACKET_HEADER_LEN, body, bodyLen );
103 }
104 this->len = bodyLen + PACKET_HEADER_LEN;
105 this->bRight = BTRUE;
106 ::LeaveCriticalSection( &(this->csAll) );
107 return ROK;
108}
109
110R32 CPacket::get( U08 *packet, U32 *packetLen, U32 maxPacketLen ) const {
111 R32 res = RERR;
112 ::EnterCriticalSection( &(this->csAll) );
113 if ( this->bRight ) {
114 res = ROK;
115 if ( packetLen != NULL ) {
116 *packetLen = this->len;
117 }
118 if ( packet != NULL ) {
119 if ( this->len <= maxPacketLen ) {
120 ::copyArray( packet, this->buffer, this->len );
121 }
122 else {
123 res = RERR;
124 }
125 }
126 }
127 ::LeaveCriticalSection( &(this->csAll) );
128 return res;
129}
130
131R32 CPacket::set( U32 packetLen, U08 *packet ) {
132 R32 res = RERR;
133 U32 bodyLen;
134 ::EnterCriticalSection( &(this->csAll) );
135 if ( (PACKET_HEADER_LEN<=packetLen) && (packetLen<=PACKET_LEN_MAX) && (packet!=NULL) ) {
136 CPacket::getU32fromNetU08( bodyLen, packet+USER_ID_LEN+USER_ID_LEN+4 );
137 if ( PACKET_HEADER_LEN + bodyLen == packetLen ) {
138 ::copyArray( this->buffer, packet, packetLen );
139 this->len = packetLen;
140 this->bRight = BTRUE;
141 res = ROK; // 这里是一个悲剧!!!!
142 }
143 }
144 ::LeaveCriticalSection( &(this->csAll) );
145 return res;
146}
147
148R32 CPacket::getU32fromNetU08( U32 &u, const U08 *p ) {
149 if ( p == NULL ) {
150 return RERR;
151 }
152 u = ( (((U32)(p[0]))<<24) | (((U32)(p[1]))<<16) | (((U32)(p[2]))<<8) | ((U32)(p[3])) );
153 return ROK;
154}
155
156R32 CPacket::getNetU08fromU32( U08 *p, U32 u ) {
157 if ( p == NULL ) {
158 return RERR;
159 }
160 p[ 0 ] = ((u>>24)&0xFF);
161 p[ 1 ] = ((u>>16)&0xFF);
162 p[ 2 ] = ((u>> 8)&0xFF);
163 p[ 3 ] = (u &0xFF);
164 return ROK;
165}
166
167R32 CPacket::recvFull( SOCKET s, U32 len, U08 *buf ) {
168 if ( buf == NULL ) {
169 return RERR;
170 }
171 I32 r;
172 U32 t = 0;
173 // if len == 0 then return ROK
174 while ( t < len ) {
175 r = ::recv( s, (char*)(buf+t), len-t, 0 );
176 if ( r <= 0 ) {
177 break;
178 }
179 t += r;
180 }
181 return ( ( t == len ) ? ROK : RERR );
182}
183
184R32 CPacket::sendFull( SOCKET s, U32 len, const U08 *buf ) {
185 if ( buf == NULL ) {
186 return RERR;
187 }
188 I32 r;
189 U32 t = 0;
190 // if len == 0 then return ROK
191 while ( t < len ) {
192 r = ::send( s, (char*)(buf+t), len-t, 0 );
193 if ( r <= 0 ) {
194 break;
195 }
196 t += r;
197 }
198 return ( ( t == len ) ? ROK : RERR );
199}
200
201R32 CPacket::ignoreRecv( SOCKET s, U32 len ) {
202 const U32 N = 128;
203 U08 buf[ N ];
204 I32 r;
205 // if len == 0 then return ROK
206 while ( len > 0 ) {
207 r = ::recv( s, (char*)buf, ((len<N)?len:N), 0 );
208 if ( r <= 0 ) {
209 break;
210 }
211 len -= r;
212 }
213 return ( ( 0 == len ) ? ROK : RERR );
214}
215
packet.h
1/**//*
2packet.h
3定义 CPacket (线程安全)
4通信数据包及辅助功能
5
6通信数据包(packet){
7 信息头(header)(大小固定){
8 USER_ID_LEN 字节 目的 ID U08 * USER_ID_LEN
9 USER_ID_LEN 字节 源 ID U08 * USER_ID_LEN
10 4 字节 命令 U32 * 1 转化为机器无关的 先高位字节,后低位字节
11 4 字节 信息字节数(仅为 信息的字节数) U32 * 1 转化为机器无关的 先高位字节,后低位字节
12 }
13 信息体(body)(大小不定,有最大限制){
14 大于等于 零 字节的数据,数据量由信息头中信息字节数指定
15 }
16}
17
18*/
19
20
21#ifndef __PACKET_H_INCLUDED__
22#define __PACKET_H_INCLUDED__
23
24
25#include "doubleLove.h"
26#include "user.h"
27
28
29 // 信息头大小
30#define PACKET_HEADER_LEN (USER_ID_LEN+USER_ID_LEN+4+4)
31 // 最大信息体大小
32#define PACKET_BODY_LEN_MAX (1024*4)
33 // 最大数据包大小
34#define PACKET_LEN_MAX ( PACKET_HEADER_LEN + PACKET_BODY_LEN_MAX )
35
36
37class CPacket
38{
39public :
40 CPacket();
41 ~CPacket();
42
43 // 阻塞接收一个完整包
44 R32 recv( SOCKET s );
45 // 阻塞发送一个完整包
46 R32 send( SOCKET s ) const;
47 // 解析一个完整包(参数为 NULL 表示不需要解析)
48 // 若使用 header ,则认为 header 空间充足
49 // 若不使用 body,则忽略 maxBodyLen
50 R32 parse( CUserId *pIdDest, CUserId *pIdSrc, U32 *pCmd, U32 *pLen, U08 *body, U32 maxBodyLen, U08 *header ) const;
51 // 构造一个完整包(参数 bodyLen 为 0 时忽略参数 body )
52 R32 build( const CUserId &idDest, const CUserId &idSrc, U32 cmd, U32 bodyLen, const U08 *body );
53
54 // 取出数据包中数据
55 // *packetLen 中返回数据包实际大小,若 packetLen 为 NULL,则忽略此参数
56 // 若 packet 为 NULL,忽略 maxPacketLen
57 R32 get( U08 *packet, U32 *packetLen, U32 maxPacketLen ) const;
58 // 设置数据包中数据,会检查包格式,不检查包内容
59 R32 set( U32 packetLen, U08 *packet );
60
61 // 辅助功能,无关线程
62 static R32 getU32fromNetU08( U32 &u, const U08 *p );
63 static R32 getNetU08fromU32( U08 *p, U32 u );
64 static R32 recvFull( SOCKET s, U32 len, U08 *buf );
65 static R32 sendFull( SOCKET s, U32 len, const U08 *buf );
66 static R32 ignoreRecv( SOCKET s, U32 len );
67
68private :
69 // 不允许拷贝
70 CPacket( const CPacket & ) {}
71 CPacket& operator=( const CPacket & ) { return (*this); }
72
73 mutable CRITICAL_SECTION csAll;
74 U08 buffer[ PACKET_LEN_MAX ];
75 U32 len;
76 B32 bRight;
77};
78
79
80#endif // __PACKET_H_INCLUDED__
81
packetCmd.h
1/**//*
2packetCmd.h
3网络通信中的命令常数
4*/
5
6
7#ifndef __PACKETCMD_H_INCLUDED__
8#define __PACKETCMD_H_INCLUDED__
9
10
11// client <<===>> server
12 // 错误
13#define PC_ERROR 10
14
15
16/**////////////////////////////////////////////////////////
17// client ===>> server
18 // 请求登录(此时信息体为 密码,长度固定为密码长度)
19#define PC_LOGON 100
20 // 请求退出
21#define PC_LOGOUT 110
22 // 请求修改密码(此时信息体为 原密码新密码,长度固定为两个密码长度)
23#define PC_MODPSW 120
24 // 请求转发数据
25#define PC_DATA 130
26 // 询问在线人数
27#define PC_NUMONLINE 140
28
29
30/**////////////////////////////////////////////////////////
31// client <<=== server
32 // 登录成功
33#define PC_LOGON_OK 10000
34 // 登录失败,在线用户过多
35#define PC_LOGON_ERR_TOOMANY 10010
36 // 登录失败,用户名密码错误
37#define PC_LOGON_ERR_IDPSW 10020
38 // 退出成功
39#define PC_LOGOUT_OK 10030
40 // 退出失败
41#define PC_LOGOUT_ERR 10040
42 // 修改密码成功
43#define PC_MODPSW_OK 10050
44 // 修改密码失败
45#define PC_MODPSW_ERR 10060
46 // 传输数据失败,对方不在线
47#define PC_DATA_ERR_NOTONLINE 10070
48 // 服务器已停止运行
49#define PC_SERVERSTOPPED 10080
50 // 用户在其它地点登录
51#define PC_LOGON_AGAIN 10090
52 // 回答在线人数
53#define PC_NUMONLINE_OK 10100
54
55
56#endif // __PACKETCMD_H_INCLUDED__
57
resource.h
1//{{NO_DEPENDENCIES}}
2// Microsoft Visual C++ generated include file.
3// Used by server_gui.rc
4//
5#define IDDIALOG_SERVER 101
6#define IDDIALOG_USER 102
7#define IDBUTTON_ADDUSER 1001
8#define IDBUTTON_DELUSER 1002
9#define IDBUTTON_MODUSER 1003
10#define IDBUTTON_QRYUSER 1004
11#define IDBUTTON_STARTSTOP 1005
12#define IDBUTTON_EXIT 1006
13#define IDSTATIC_SERVERIP 1007
14#define IDSTATIC_SERVERPORT 1008
15#define IDEDIT_SERVERPORT 1009
16#define IDCOMBO_SERVERIP 1011
17#define IDSTATIC_NAME 1012
18#define IDSTATIC_ID 1013
19#define IDSTATIC_PSW 1014
20#define IDBUTTON_OK 1015
21#define IDBUTTON_CANCEL 1016
22#define IDEDIT_NAME 1017
23#define IDEDIT_ID 1018
24#define IDEDIT_PSW 1019
25#define IDBUTTON_HELP 1020
26
27// Next default values for new objects
28//
29#ifdef APSTUDIO_INVOKED
30#ifndef APSTUDIO_READONLY_SYMBOLS
31#define _APS_NEXT_RESOURCE_VALUE 103
32#define _APS_NEXT_COMMAND_VALUE 40001
33#define _APS_NEXT_CONTROL_VALUE 1021
34#define _APS_NEXT_SYMED_VALUE 101
35#endif
36#endif
37
server.cpp
1/**//*
2server.cpp
3实现 CServer 及相关线程
4服务器功能,无关界面
5*/
6
7
8#include "server.h"
9#include "serverDefaultInfo.h"
10#include "packet.h"
11#include "serverThreadData.h"
12#include "serverThreadCenter.h"
13#include "threadCmd.h"
14#include "packetCmd.h"
15#include "toolSz.h"
16#include <process.h>
17#include <string.h>
18
19
20#pragma comment( lib, "ws2_32.lib" )
21
22
23static CServerThreadCenter threadCenter;
24
25
26static unsigned __stdcall dealDispatch( void *pParam ) {
27 PtrCServerThreadData pData = (PtrCServerThreadData)pParam, pDest;
28 CPacket packet;
29 const U32 BODY_LEN = USER_PSW_LEN + USER_PSW_LEN + 256;
30 U08 body[ BODY_LEN ];
31 CUserId idSrc, idDest, idServer, idSrcLogon;
32 CUserPsw pswOld, pswNew;
33 U32 packetCmd, len, threadCmd;
34 R32 res;
35 SOCKET skSrc = INVALID_SOCKET, skDest = INVALID_SOCKET;
36 CServer *pServer = NULL;
37
38#define EXITM { \
39 ::closesocket( skSrc ); \
40 skSrc = INVALID_SOCKET; \
41 ::threadCenter.free( pData ); \
42 return 0; \
43 }
44
45 // 尚未登录,无需发送绑定,其它服务线程对自己的发送绑定必将失败,其他用户无法向自己发数据
46#define BACKC(c) { \
47 packet.build( idSrc, idServer, c, 0, NULL ); \
48 res = packet.send( skSrc ); \
49 }
50
51 // 登录后,发数据需绑定,以确保独占发送,从而确保数据包完整不混合
52#define SENDC(c) { \
53 packet.build( idSrc, idServer, c, 0, NULL ); \
54 res = RERR; \
55 if ( ROK == ::threadCenter.sendLock( idSrc, pDest ) ) { \
56 if ( ROK == pDest->getSocket( skDest ) ) { \
57 res = packet.send( skDest ); \
58 } \
59 ::threadCenter.sendUnlock( pDest ); \
60 } \
61 }
62
63 // 成功登录后退出
64#define EXITC(c) { \
65 SENDC(c) \
66 EXITM \
67 }
68
69 // 尚未登录即退出
70#define FAILC(c) { \
71 BACKC(c) \
72 EXITM \
73 }
74
75 if ( pData->getSocket( skSrc ) != ROK ) {
76 ::threadCenter.free( pData );
77 return 0;
78 }
79 if ( pData->getServer( pServer ) != ROK ) {
80 EXITM;
81 }
82 pServer->getId( idServer );
83 res = packet.recv( skSrc );
84 if ( res != ROK ) {
85 EXITM;
86 }
87 // res = packet.parse( &idDest, &idSrc, &packetCmd, &len, NULL, 0, NULL );
88 res = packet.parse( &idDest, &idSrc, &packetCmd, &len, body, BODY_LEN, NULL );
89
90 if ( (res == ROK) && (packetCmd == PC_LOGON) ) {
91 if ( ( len != USER_PSW_LEN ) || ( idDest != idServer ) ) {
92 FAILC( PC_ERROR );
93 }
94 // 假设相同 ID 先前已登录,尝试关闭之
95 SENDC( PC_LOGON_AGAIN );
96 if ( res == ROK ) {
97 // 相同 ID 先前已登录,关闭其连接
98 ::closesocket( skDest );
99 ::Sleep( 16 );
100 }
101 // 当前在线用户过多
102 if ( ::threadCenter.getNumOnline() >= ONLINE_NUM_MAX ) {
103 FAILC( PC_LOGON_ERR_TOOMANY );
104 }
105
106 CUser user;
107 user.id = idSrc;
108 user.psw = body;
109 if ( ! pServer->isUser( user ) ) {
110 FAILC( PC_LOGON_ERR_IDPSW );
111 }
112 }
113 else {
114 FAILC( PC_ERROR );
115 }
116
117 BACKC( PC_LOGON_OK );
118 if ( res != ROK ) {
119 EXITM;
120 }
121 if ( ::threadCenter.logon( pData, idSrc ) != ROK ) {
122 FAILC( PC_ERROR );
123 }
124 idSrcLogon = idSrc;
125
126 res = ROK;
127 while ( res == ROK ) {
128 while ( ( pData->getCmd( threadCmd ) != ROK ) && ( res == ROK ) ) {
129 res = packet.recv( skSrc );
130 if ( res != ROK ) {
131 continue;
132 }
133 res = packet.parse( &idDest, &idSrc, &packetCmd, &len, NULL, 0, NULL );
134 if ( res != ROK ) {
135 continue;
136 }
137 if ( idSrc != idSrcLogon ) {
138 SENDC( PC_ERROR );
139 res = RERR;
140 continue;
141 }
142 switch ( packetCmd ) {
143 case PC_DATA :
144 if ( ROK != ::threadCenter.sendLock( idDest, pDest ) ) {
145 SENDC( PC_DATA_ERR_NOTONLINE );
146 break;
147 }
148 res = pDest->getSocket( skDest );
149 if ( res != ROK ) {
150 break;
151 }
152 if ( pDest->isOnline() ) {
153 res = packet.send( skDest );
154 }
155 else {
156 SENDC( PC_DATA_ERR_NOTONLINE );
157 }
158 ::threadCenter.sendUnlock( pDest );
159 break;
160 case PC_MODPSW :
161 if ( len != USER_PSW_LEN + USER_PSW_LEN ) {
162 SENDC( PC_ERROR );
163 res = RERR;
164 }
165 else {
166 packet.parse( NULL, NULL, NULL, NULL, body, BODY_LEN, NULL );
167 pswOld = body;
168 pswNew = body + USER_PSW_LEN;
169 res = pServer->modPsw( idSrc, pswOld, pswNew );
170 if ( res == ROK ) {
171 SENDC( PC_MODPSW_OK );
172 }
173 else {
174 SENDC( PC_MODPSW_ERR );
175 }
176 }
177 break;
178 case PC_LOGOUT :
179 if ( len != 0 ) {
180 SENDC( PC_ERROR );
181 }
182 else {
183 SENDC( PC_LOGOUT_OK );
184 }
185 res = RERR;
186 break;
187 case PC_NUMONLINE :
188 CPacket::getNetU08fromU32( body, ::threadCenter.getNumOnline() );
189 packet.build( idSrc, idServer, PC_NUMONLINE_OK, 4, body );
190 res = RERR;
191 if ( ROK == ::threadCenter.sendLock( idSrc, pDest ) ) {
192 if ( ROK == pDest->getSocket( skDest ) ) {
193 res = packet.send( skDest );
194 }
195 ::threadCenter.sendUnlock( pDest );
196 }
197 break;
198 default :
199 SENDC( PC_ERROR );
200 res = RERR;
201 break;
202 }
203 }
204 switch ( threadCmd ) {
205 case TC_EMPTY :
206 break;
207 case TC_SERVERSTOPPED :
208 SENDC( TC_SERVERSTOPPED );
209 res = RERR;
210 break;
211 default :
212 res = RERR;
213 break;
214 }
215 }
216
217 ::threadCenter.logout( pData );
218 EXITM;
219
220#undef FAILC
221#undef EXITC
222#undef SENDC
223#undef BACKC
224#undef EXITM
225}
226
227
228static unsigned __stdcall dealListen( void *pParam ) {
229 PtrCServerThreadData pData = (PtrCServerThreadData)pParam;
230 PtrCServerThreadData pNew;
231 SOCKET skListen = INVALID_SOCKET, skClient;
232 SOCKADDR_IN addrClient;
233 I32 lenAddr;
234 U32 cmd;
235 CServer *pServer;
236 R32 res = ROK;
237 while ( res == ROK ) {
238 while ( ( pData->getCmd(cmd) != ROK ) && ( res == ROK ) ) {
239 res = pData->getSocket( skListen );
240 if ( res != ROK ) {
241 continue;
242 }
243 lenAddr = sizeof(addrClient);
244 skClient = ::accept( skListen, (sockaddr*)(&addrClient), &lenAddr );
245 if ( skClient == INVALID_SOCKET ) {
246 res = RERR;
247 continue;
248 }
249 res = pData->getServer( pServer );
250 if ( res != ROK ) {
251 ::closesocket( skClient );
252 continue;
253 }
254 res = threadCenter.alloc( pNew, skClient, addrClient, pServer );
255 if ( res != ROK ) {
256 ::closesocket( skClient );
257 continue;
258 }
259 ::_beginthreadex( NULL, 0, dealDispatch, (void*)pNew, 0, NULL );
260 }
261 switch ( cmd ) {
262 case TC_EMPTY :
263 break;
264 case TC_SERVERSTOPPED :
265 ::closesocket( skListen );
266 res = RERR;
267 break;
268 default :
269 res = RERR;
270 break;
271 }
272 }
273 threadCenter.free( pData );
274 return 0;
275}
276
277
278CServer::CServer() {
279 ::InitializeCriticalSection( &(this->csAll) );
280
281 U08 idServer[] = SERVER_ID_DEFAULT;
282 this->id = idServer;
283
284 this->bQryFirst = BFALSE;
285 this->pFind = this->pUser = NULL;
286
287 this->state = SS_STOP;
288
289 this->sock = INVALID_SOCKET;
290 ::memset( &(this->addr), 0, sizeof(this->addr) );
291 this->addr.sin_family = AF_INET;
292 this->addr.sin_port = ::htons( SERVER_PORT_DEFAULT );
293 this->addr.sin_addr.S_un.S_addr = INADDR_ANY;
294}
295
296CServer::~CServer() {
297 this->delAllUser();
298 ::DeleteCriticalSection( &(this->csAll) );
299}
300
301
302R32 CServer::start() {
303 R32 res = RERR;
304 ::EnterCriticalSection( &(this->csAll) );
305 do {
306 if ( this->state == SS_RUNNING ) {
307 res = ROK;
308 break;
309 }
310 ::WSADATA wsadata;
311 if ( ::WSAStartup( MAKEWORD(2,2), &wsadata ) ) {
312 break;
313 }
314 this->sock = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
315 if ( this->sock == INVALID_SOCKET ) {
316 ::WSACleanup();
317 break;
318 }
319 if ( ::bind( this->sock, (sockaddr*)(&(this->addr)), sizeof(this->addr) ) ) {
320 ::closesocket( this->sock );
321 this->sock = INVALID_SOCKET;
322 ::WSACleanup();
323 break;
324 }
325 if ( ::listen( this->sock, SOMAXCONN ) ) {
326 ::closesocket( this->sock );
327 this->sock = INVALID_SOCKET;
328 ::WSACleanup();
329 break;
330 }
331 PtrCServerThreadData pData;
332 if ( ROK != ::threadCenter.alloc( pData, this->sock, this->addr, this ) ) {
333 ::closesocket( this->sock );
334 this->sock = INVALID_SOCKET;
335 ::WSACleanup();
336 break;
337 }
338 ::_beginthreadex( NULL, 0, dealListen, (void*)pData, 0, NULL );
339 this->state = SS_RUNNING;
340 res = ROK;
341 } while ( BFALSE );
342 ::LeaveCriticalSection( &(this->csAll) );
343 return res;
344}
345
346R32 CServer::stop() {
347 R32 res = RERR;
348 ::EnterCriticalSection( &(this->csAll) );
349 if ( this->state != SS_STOP ) {
350 ::threadCenter.sendAllCmd( TC_SERVERSTOPPED, TRUE ); // 写命令,不必等待应答,可再次启动
351 ::closesocket( this->sock ); // 监听线程 accept 为阻塞工作
352 this->sock = INVALID_SOCKET;
353 ::WSACleanup();
354 this->state = SS_STOP;
355 }
356 res = ROK;
357 ::LeaveCriticalSection( &(this->csAll) );
358 return res;
359}
360
361
362R32 CServer::getId( CUserId &serverid ) {
363 ::EnterCriticalSection( &(this->csAll) );
364 serverid = this->id;
365 ::LeaveCriticalSection( &(this->csAll) );
366 return ROK;
367}
368
369R32 CServer::initPort( U16 port ) {
370 R32 res = RERR;
371 ::EnterCriticalSection( &(this->csAll) );
372 if ( this->state == SS_STOP ) {
373 res = ROK;
374 this->addr.sin_port = ::htons( port );
375 }
376 ::LeaveCriticalSection( &(this->csAll) );
377 return res;
378}
379
380R32 CServer::initIp( U32 ip ) {
381 R32 res = RERR;
382 ::EnterCriticalSection( &(this->csAll) );
383 if ( this->state == SS_STOP ) {
384 res = ROK;
385 this->addr.sin_addr.S_un.S_addr = ip;
386 }
387 ::LeaveCriticalSection( &(this->csAll) );
388 return res;
389}
390
391U16 CServer::getPort() const {
392 U16 p;
393 ::EnterCriticalSection( &(this->csAll) );
394 p = ::ntohs( this->addr.sin_port );
395 ::LeaveCriticalSection( &(this->csAll) );
396 return p;
397}
398
399U32 CServer::getState() const {
400 U32 s;
401 ::EnterCriticalSection( &(this->csAll) );
402 s = this->state;
403 ::LeaveCriticalSection( &(this->csAll) );
404 return s;
405}
406
407R32 CServer::listHostIp( U32 *ipList, U32 &ipNum, U32 maxIpNum ) {
408 if ( ipList == NULL ) {
409 return RERR;
410 }
411 R32 res = RERR;
412 ::EnterCriticalSection( &(this->csAll) );
413 if ( this->state == SS_STOP ) {
414 do {
415 WSADATA wsa;
416 if ( ::WSAStartup( MAKEWORD(2,2), &wsa ) ) {
417 break;
418 }
419 C08 name[ 512 ];
420 PHOSTENT host;
421 if ( ::gethostname( name, 512 ) ) {
422 ::WSACleanup();
423 break;
424 }
425 host = ::gethostbyname( name );
426 if ( host == NULL ) {
427 ::WSACleanup();
428 break;
429 }
430 IN_ADDR addr;
431 for ( ipNum = 0; ( ipNum < maxIpNum ) && ( host->h_addr_list[ ipNum ] != NULL ); ++ipNum ) {
432 ::memcpy( &addr, host->h_addr_list[ ipNum ], host->h_length );
433 ipList[ ipNum++ ] = addr.S_un.S_addr;
434 }
435 ::WSACleanup();
436 res = ROK;
437 } while ( BFALSE );
438 }
439 ::LeaveCriticalSection( &(this->csAll) );
440 return res;
441}
442
443
444R32 CServer::addUser( const CUser &user ) {
445 R32 res = RERR;
446 CUserNode *p = NULL;
447 ::EnterCriticalSection( &(this->csAll) );
448 for ( p = this->pUser; (p != NULL) && (p->u.id != user.id); p = p->next ) {
449 }
450 if ( p == NULL ) {
451 p = new CUserNode;
452 p->u = user;
453 p->next = this->pUser;
454 this->pUser = p;
455 res = ROK;
456 this->bQryFirst = BFALSE;
457 }
458 ::LeaveCriticalSection( &(this->csAll) );
459 return res;
460}
461
462R32 CServer::delUser( const CUser &user ){
463 R32 res = RERR;
464 CUserNode *p = NULL, *q = NULL;
465 ::EnterCriticalSection( &(this->csAll) );
466 for ( p = this->pUser; (p != NULL) && (p->u.id != user.id); p = p->next ) {
467 q = p;
468 }
469 if ( p != NULL ) {
470 if ( q != NULL ) {
471 q->next = p->next;
472 }
473 else {
474 this->pUser = p->next;
475 }
476 delete p;
477 res = ROK;
478 this->bQryFirst = BFALSE;
479 }
480 ::LeaveCriticalSection( &(this->csAll) );
481 return res;
482}
483
484R32 CServer::delAllUser() {
485 CUserNode *p = NULL, *q = NULL;
486 ::EnterCriticalSection( &(this->csAll) );
487 for ( p = this->pUser; p != NULL; p = q ) {
488 q = p->next;
489 delete p;
490 }
491 this->pUser = this->pFind = NULL;
492 this->bQryFirst = BFALSE;
493 ::LeaveCriticalSection( &(this->csAll) );
494 return ROK;
495}
496
497R32 CServer::modUser( const CUser &user ) {
498 R32 res = RERR;
499 CUserNode *p = NULL;
500 ::EnterCriticalSection( &(this->csAll) );
501 for ( p = this->pUser; (p != NULL) && (p->u.id != user.id); p = p->next ) {
502 }
503 if ( p != NULL ) {
504 p->u = user;
505 res = ROK;
506 this->bQryFirst = BFALSE;
507 }
508 ::LeaveCriticalSection( &(this->csAll) );
509 return res;
510}
511
512R32 CServer::qryUser( CUser &user, B32 byId, B32 first ) const {
513 R32 res = RERR;
514 ::EnterCriticalSection( &(this->csAll) );
515 if ( byId ) {
516 this->bQryFirst = BFALSE;
517 for ( this->pFind = this->pUser;
518 (this->pFind != NULL) && (this->pFind->u.id != user.id);
519 this->pFind = this->pFind->next ) {
520 }
521 if ( this->pFind != NULL ) {
522 user = this->pFind->u;
523 res = ROK;
524 }
525 }
526 else {
527 if ( first ) {
528 this->bQryFirst = BTRUE;
529 for ( this->pFind = this->pUser;
530 (this->pFind != NULL) && (this->pFind->u.name != user.name);
531 this->pFind = this->pFind->next ) {
532 }
533 if ( this->pFind != NULL ) {
534 user = this->pFind->u;
535 res = ROK;
536 }
537 }
538 else if ( this->bQryFirst ) {
539 if ( this->pFind != NULL ) {
540 do {
541 this->pFind = this->pFind->next;
542 } while ( (this->pFind != NULL) && (this->pFind->u.name != user.name) );
543 if ( this->pFind != NULL ) {
544 res = ROK;
545 user = this->pFind->u;
546 }
547 }
548 }
549 }
550 ::LeaveCriticalSection( &(this->csAll) );
551 return res;
552}
553
554R32 CServer::modPsw( const CUserId &id, const CUserPsw &pswOld, const CUserPsw &pswNew ) {
555 R32 res = RERR;
556 CUserNode *p = NULL;
557 ::EnterCriticalSection( &(this->csAll) );
558 for ( p = this->pUser; (p != NULL) && (p->u.id != id); p = p->next ) {
559 }
560 if ( ( p != NULL ) && ( p->u.psw == pswOld ) ) {
561 res = ROK;
562 p->u.psw = pswNew;
563 this->bQryFirst = BFALSE;
564 }
565 ::LeaveCriticalSection( &(this->csAll) );
566 return res;
567}
568
569B32 CServer::isUser( const CUser &user ) const {
570 B32 is = BFALSE;
571 CUserNode *p = NULL;
572 ::EnterCriticalSection( &(this->csAll) );
573 for ( p = this->pUser; (p != NULL) && (p->u.id != user.id); p = p->next ) {
574 }
575 if ( p != NULL ) {
576 is = ( p->u.psw == user.psw );
577 }
578 ::LeaveCriticalSection( &(this->csAll) );
579 return is;
580}
581
server.h
1/**//*
2server.h
3定义 CServer(线程安全)
4服务器功能,无关界面
5*/
6
7
8#ifndef __SERVER_H_INCLUDED__
9#define __SERVER_H_INCLUDED__
10
11
12#include "doubleLove.h"
13#include "user.h"
14
15
16 // 服务器运行状态
17 // 已经停止
18#define SS_STOP 0
19 // 正在运行
20#define SS_RUNNING 10
21
22
23class CUserNode
24{
25public :
26 CUser u;
27 CUserNode *next;
28};
29
30
31// SOCKET 分散管理,各个服务线程自己负责关闭
32
33class CServer
34{
35public :
36 CServer();
37 ~CServer();
38
39 R32 start();
40 R32 stop();
41
42 R32 getId( CUserId &serverid );
43 R32 initPort( U16 port );
44 R32 initIp( U32 ip );
45 U16 getPort() const;
46 U32 getState() const;
47 // 列举服务器可用 IPv4,IN_ADDR 格式
48 R32 listHostIp( U32 *ipList, U32 &ipNum, U32 maxIpNum );
49
50 R32 addUser( const CUser &user ); // 增加用户 NAME, ID, PSW
51 R32 delUser( const CUser &user ); // 以 ID 识别用户
52 R32 delAllUser();
53 R32 modUser( const CUser &user ); // 以 ID 识别用户,修改 NAME,PSW
54 // 以 NAME ID 之一查询,默认使用 ID
55 // 使用 ID 时,first 参数被忽略
56 // 使用 NAME 时,first 为 BTRUE 时从第一个开始找;为 BFALSE 时,从上一次找到的下一个开始找
57 // 使用 NAME 查找下一个时,不要在两次查找之间混入其他用户修改操作
58 R32 qryUser( CUser &user, B32 byId = BTRUE, B32 first = BTRUE ) const;
59 R32 modPsw( const CUserId &id, const CUserPsw &pswOld, const CUserPsw &pswNew ); // 修改密码
60 B32 isUser( const CUser &user ) const; // 核对 ID,PSW 确定是否是合法用户
61
62private :
63 mutable CRITICAL_SECTION csAll;
64
65 CUserNode *pUser;
66 mutable CUserNode *pFind;
67 mutable B32 bQryFirst;
68
69 CUserId id;
70 U32 state;
71 SOCKET sock;
72 SOCKADDR_IN addr; // 服务器地址,网络字节序
73};
74
75
76#endif // __SERVER_H_INCLUDED__
77
server_gui.cpp
1/**//*
2server_gui.cpp
3服务器端 图形界面
4*/
5
6
7#include "resource.h"
8#include "doubleLove.h"
9#include "server.h"
10#include "toolSz.h"
11
12
13CServer server;
14HINSTANCE hInstance;
15
16
17 // 管理用户
18BOOL CALLBACK DlgUserProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
19 static LPARAM reason;
20
21 const U32 NAME_BUF_LEN = USER_NAME_LEN_MAX + 64;
22 C16 namebuf[ NAME_BUF_LEN + 4 ];
23 U32 namelen;
24
25 const U32 ID_BUF_LEN = USER_ID_LEN + 4;
26 C16 idcbuf[ ID_BUF_LEN + 4 ];
27 U08 idbuf[ ID_BUF_LEN + 4 ];
28 U32 idlen;
29
30 const U32 PSW_BUF_LEN = USER_PSW_LEN + 4;
31 C16 pswcbuf[ PSW_BUF_LEN + 4 ];
32 U08 pswbuf[ PSW_BUF_LEN + 4 ];
33 U32 pswlen;
34
35 CUser user;
36 static B32 bNameFirst = BFALSE;
37
38 switch ( uMsg ) {
39 case WM_INITDIALOG :
40 reason = lParam;
41 bNameFirst = BFALSE;
42 switch ( lParam ) {
43 case IDBUTTON_ADDUSER :
44 ::SetWindowText( hDlg, TEXT("增加用户") );
45 break;
46 case IDBUTTON_DELUSER :
47 ::SetWindowText( hDlg, TEXT("删除用户") );
48 ::EnableWindow( ::GetDlgItem( hDlg, IDEDIT_NAME ), FALSE );
49 ::EnableWindow( ::GetDlgItem( hDlg, IDEDIT_PSW ), FALSE );
50 break;
51 case IDBUTTON_MODUSER :
52 ::SetWindowText( hDlg, TEXT("修改用户") );
53 break;
54 case IDBUTTON_QRYUSER :
55 ::SetWindowText( hDlg, TEXT("查询用户") );
56 ::EnableWindow( ::GetDlgItem( hDlg, IDEDIT_PSW ), FALSE );
57 break;
58 }
59 return TRUE;
60 case WM_COMMAND :
61 switch ( LOWORD(wParam) ) {
62 case IDBUTTON_OK :
63 namelen = ::GetDlgItemText( hDlg, IDEDIT_NAME, namebuf, NAME_BUF_LEN );
64 user.name = namebuf;
65 idlen = ::GetDlgItemText( hDlg, IDEDIT_ID, idcbuf, ID_BUF_LEN );
66 ::copyArray( idbuf, idcbuf, USER_ID_LEN );
67 user.id = idbuf;
68 pswlen = ::GetDlgItemText( hDlg, IDEDIT_PSW, pswcbuf, PSW_BUF_LEN );
69 ::copyArray( pswbuf, pswcbuf, USER_PSW_LEN );
70 user.psw = pswbuf;
71 switch ( reason ) {
72 case IDBUTTON_ADDUSER :
73 if ( (idlen==USER_ID_LEN) && (pswlen==USER_PSW_LEN) && (namelen<=USER_NAME_LEN_MAX) ) {
74 if ( server.addUser( user ) == ROK ) {
75 ::MessageBox( hDlg, TEXT("添加成功"), TEXT("成功"), MB_OK|MB_ICONINFORMATION );
76 ::SetDlgItemText( hDlg, IDEDIT_NAME, TEXT("") );
77 ::SetDlgItemText( hDlg, IDEDIT_ID, TEXT("") );
78 ::SetDlgItemText( hDlg, IDEDIT_PSW, TEXT("") );
79 }
80 else {
81 ::MessageBox( hDlg, TEXT("添加失败"), TEXT("失败"), MB_OK|MB_ICONINFORMATION );
82 }
83 }
84 else {
85 ::MessageBox( hDlg, TEXT("格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
86 }
87 return TRUE;
88 case IDBUTTON_DELUSER :
89 if ( idlen == USER_ID_LEN ) {
90 if ( server.delUser( user ) == ROK ) {
91 ::MessageBox( hDlg, TEXT("删除成功"), TEXT("成功"), MB_OK|MB_ICONINFORMATION );
92 ::SetDlgItemText( hDlg, IDEDIT_ID, TEXT("") );
93 }
94 else {
95 ::MessageBox( hDlg, TEXT("删除失败"), TEXT("失败"), MB_OK|MB_ICONINFORMATION );
96 }
97 }
98 else {
99 ::MessageBox( hDlg, TEXT("格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
100 }
101 return TRUE;
102 case IDBUTTON_MODUSER :
103 if ( (idlen==USER_ID_LEN) && (pswlen==USER_PSW_LEN) ) {
104 if ( server.modUser( user ) == ROK ) {
105 ::MessageBox( hDlg, TEXT("修改成功"), TEXT("成功"), MB_OK|MB_ICONINFORMATION );
106 ::SetDlgItemText( hDlg, IDEDIT_NAME, TEXT("") );
107 ::SetDlgItemText( hDlg, IDEDIT_ID, TEXT("") );
108 ::SetDlgItemText( hDlg, IDEDIT_PSW, TEXT("") );
109 }
110 else {
111 ::MessageBox( hDlg, TEXT("修改失败"), TEXT("失败"), MB_OK|MB_ICONINFORMATION );
112 }
113 }
114 else {
115 ::MessageBox( hDlg, TEXT("格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
116 }
117 return TRUE;
118 case IDBUTTON_QRYUSER :
119 if ( (namelen>0) && (idlen>0) && (!bNameFirst) ) {
120 ::MessageBox( hDlg, TEXT("根据其中一个关键字查询"), TEXT("错误"), MB_OK|MB_ICONERROR );
121 return TRUE;
122 }
123 if ( (namelen==0) && (idlen==0) ) {
124 ::MessageBox( hDlg, TEXT("格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
125 return TRUE;
126 }
127 if ( namelen > 0 ) {
128 R32 res;
129 if ( bNameFirst ) {
130 res = server.qryUser( user, BFALSE, BFALSE );
131 }
132 else {
133 bNameFirst = BTRUE;
134 res = server.qryUser( user, BFALSE, BTRUE );
135 }
136 if ( res == ROK ) {
137 user.id.getU08( idbuf );
138 ::copyArray( idcbuf, idbuf, USER_ID_LEN );
139 idcbuf[ USER_ID_LEN ] = 0;
140 ::SetDlgItemText( hDlg, IDEDIT_ID, idcbuf );
141 user.psw.getU08( pswbuf );
142 ::copyArray( pswcbuf, pswbuf, USER_PSW_LEN );
143 pswcbuf[ USER_PSW_LEN ] = 0;
144 ::SetDlgItemText( hDlg, IDEDIT_PSW, pswcbuf );
145 }
146 else {
147 ::MessageBox( hDlg, TEXT("查找失败"), TEXT("失败"), MB_OK|MB_ICONINFORMATION );
148 }
149 return TRUE;
150 }
151 if ( idlen != USER_ID_LEN ) {
152 ::MessageBox( hDlg, TEXT("格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
153 }
154 else {
155 bNameFirst = BFALSE;
156 if ( ROK == server.qryUser( user, BTRUE ) ) {
157 user.name.getSz16( namebuf );
158 ::SetDlgItemText( hDlg, IDEDIT_NAME, namebuf );
159 user.psw.getU08( pswbuf );
160 ::copyArray( pswcbuf, pswbuf, USER_PSW_LEN );
161 pswcbuf[ USER_PSW_LEN ] = 0;
162 ::SetDlgItemText( hDlg, IDEDIT_PSW, pswcbuf );
163 }
164 else {
165 ::MessageBox( hDlg, TEXT("查找失败"), TEXT("失败"), MB_OK|MB_ICONINFORMATION );
166 }
167 }
168 return TRUE;
169 }
170 return TRUE;
171 case IDBUTTON_CANCEL :
172 ::EndDialog( hDlg, 0 );
173 return TRUE;
174 case IDEDIT_NAME :
175 bNameFirst = BFALSE;
176 return TRUE;
177 case IDEDIT_ID :
178 return TRUE;
179 case IDEDIT_PSW :
180 return TRUE;
181 }
182 break;
183 case WM_CLOSE :
184 ::PostMessage( hDlg, WM_COMMAND, IDBUTTON_CANCEL, 0 );
185 break;
186 }
187 return FALSE;
188}
189
190
191BOOL CALLBACK DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
192 #define IP_NUM_MAX 512
193 static U32 ipList[ IP_NUM_MAX ];
194 static U32 ipNum, ipSelIdx;
195
196 #define SZ_LEN_MAX 512
197 static C16 sz[ SZ_LEN_MAX+4 ];
198
199 U32 i;
200
201 switch ( uMsg ) {
202 case WM_INITDIALOG :
203 ::SetDlgItemInt( hDlg, IDEDIT_SERVERPORT, server.getPort(), FALSE );
204 server.listHostIp( ipList, ipNum, IP_NUM_MAX );
205 for ( i = 0; i < ipNum; ++i ) {
206 IN_ADDR addr;
207 addr.S_un.S_addr = ipList[ i ];
208 ::getSz16fromSz08( sz, ::inet_ntoa( addr ), SZ_LEN_MAX );
209 ::SendMessage( ::GetDlgItem( hDlg, IDCOMBO_SERVERIP ), CB_ADDSTRING, 0, (LPARAM)(sz) );
210 }
211 if ( ipNum > 0 ) {
212 ipSelIdx = 0;
213 ::SendMessage( ::GetDlgItem( hDlg, IDCOMBO_SERVERIP ), CB_SETCURSEL, ipSelIdx, 0 );
214 // test
215 /**///////// server.initIp( ipList[ ipSelIdx ] );
216 // end
217 }
218 return TRUE;
219 case WM_COMMAND :
220 switch ( LOWORD(wParam) ) {
221 case IDBUTTON_ADDUSER :
222 case IDBUTTON_DELUSER :
223 case IDBUTTON_MODUSER :
224 case IDBUTTON_QRYUSER :
225 ::DialogBoxParam( ::hInstance, MAKEINTRESOURCE(IDDIALOG_USER), hDlg, DlgUserProc, LOWORD(wParam) );
226 return TRUE;
227 case IDBUTTON_STARTSTOP :
228 if ( server.getState() == SS_STOP ) {
229 if ( ipNum > 0 ) {
230 BOOL res;
231 UINT u = ::GetDlgItemInt( hDlg, IDEDIT_SERVERPORT, &res, FALSE );
232 if ( (res) && (u<=0xFFFF) ) {
233 server.initPort( (U16)u );
234 i = (U32)(::SendMessage( (HWND)(lParam), CB_GETCURSEL, 0, 0 ));
235 if ( i != CB_ERR ) {
236 ipSelIdx = i;
237 // test
238 /**///////// server.initIp( ipList[ ipSelIdx ] );
239 // end
240 server.start();
241 }
242 }
243 else {
244 ::MessageBox( hDlg, TEXT("端口号不合法"), TEXT("错误"), MB_OK|MB_ICONERROR );
245 }
246 }
247 else {
248 ::MessageBox( hDlg, TEXT("无可用 IP"), TEXT("错误"), MB_OK|MB_ICONERROR );
249 }
250 }
251 else {
252 server.stop();
253 }
254 if ( server.getState() == SS_STOP ) {
255 ::SetDlgItemText( hDlg, IDBUTTON_STARTSTOP, TEXT("启动") );
256 ::EnableWindow( ::GetDlgItem( hDlg, IDEDIT_SERVERPORT ), TRUE );
257 ::EnableWindow( ::GetDlgItem( hDlg, IDCOMBO_SERVERIP ), TRUE );
258 }
259 else {
260 ::SetDlgItemText( hDlg, IDBUTTON_STARTSTOP, TEXT("停止") );
261 ::EnableWindow( ::GetDlgItem( hDlg, IDEDIT_SERVERPORT ), FALSE );
262 ::EnableWindow( ::GetDlgItem( hDlg, IDCOMBO_SERVERIP ), FALSE );
263 }
264 return TRUE;
265 case IDBUTTON_EXIT :
266 server.stop();
267 ::EndDialog( hDlg, 0 );
268 return TRUE;
269 case IDEDIT_SERVERPORT :
270 return TRUE;
271 case IDCOMBO_SERVERIP :
272 return TRUE;
273 case IDBUTTON_HELP :
274 ::MessageBox( hDlg, TEXT("昵称不超过16个字符,可使用汉字\n账号为10个数字\n密码为10个数字\n\n"), TEXT("帮助"), MB_OK|MB_ICONINFORMATION );
275 return TRUE;
276 }
277 break;
278 case WM_CLOSE :
279 ::PostMessage( hDlg, WM_COMMAND, IDBUTTON_EXIT, 0 );
280 break;
281 }
282 return FALSE;
283}
284
285
286int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR lpCmd, INT nShow ) {
287 // test
288 {
289 U08 id[ USER_ID_LEN + 4 ] = { 0 };
290 U08 psw[ USER_PSW_LEN + 4 ] = { 0 };
291 U32 i, j;
292 CUser user;
293 for ( i = 0; i < USER_ID_LEN; ++i ) {
294 id[ i ] = T08('1');
295 }
296 for ( i = 0; i < USER_PSW_LEN; ++i ) {
297 psw[ i ] = T08('1');
298 }
299 user.name = T16("zj");
300 user.psw = psw;
301 for ( i = 1; i <= 9; ++i ) {
302 for ( j = 1; j <= 9; ++j ) {
303 id[ 0 ] = T08('0') + i;
304 id[ 1 ] = T08('0') + j;
305 user.id = id;
306 server.addUser( user );
307 }
308 }
309#ifdef DEBUG
310 for ( i = 0; i < USER_ID_LEN; ++i ) {
311 id[ i ] = T08('1');
312 }
313 for ( i = 0; i < USER_PSW_LEN; ++i ) {
314 psw[ i ] = T08('1');
315 }
316 user.id = id;
317 user.psw = psw;
318#endif
319 }
320 // end
321
322
323 ::hInstance = hInst;
324 ::DialogBoxParam( hInst, MAKEINTRESOURCE(IDDIALOG_SERVER), NULL, DlgProc, 0 );
325 return 0;
326}
327
server_gui.rc
1// Microsoft Visual C++ generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/**//////////////////////////////////////////////////////////////////////////////
7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/**//////////////////////////////////////////////////////////////////////////////
13#undef APSTUDIO_READONLY_SYMBOLS
14
15/**//////////////////////////////////////////////////////////////////////////////
16// Chinese (Simplified, PRC) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
19LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
20
21#ifdef APSTUDIO_INVOKED
22/**//////////////////////////////////////////////////////////////////////////////
23//
24// TEXTINCLUDE
25//
26
271 TEXTINCLUDE
28BEGIN
29 "resource.h\0"
30END
31
322 TEXTINCLUDE
33BEGIN
34 "#include ""afxres.h""\r\n"
35 "\0"
36END
37
383 TEXTINCLUDE
39BEGIN
40 "\r\n"
41 "\0"
42END
43
44#endif // APSTUDIO_INVOKED
45
46
47/**//////////////////////////////////////////////////////////////////////////////
48//
49// Dialog
50//
51
52IDDIALOG_SERVER DIALOGEX 300, 150, 316, 182
53STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
54CAPTION "doubleLove 服务器端"
55FONT 8, "MS Shell Dlg", 400, 0, 0x1
56BEGIN
57 PUSHBUTTON "增加用户",IDBUTTON_ADDUSER,20,105,50,14
58 PUSHBUTTON "删除用户",IDBUTTON_DELUSER,90,105,50,14
59 PUSHBUTTON "修改用户",IDBUTTON_MODUSER,160,105,50,14
60 PUSHBUTTON "查询用户",IDBUTTON_QRYUSER,230,105,50,14
61 PUSHBUTTON "退出",IDBUTTON_EXIT,154,144,50,14
62 LTEXT "服务器 IP",IDSTATIC_SERVERIP,20,30,45,14
63 LTEXT "服务器端口",IDSTATIC_SERVERPORT,20,60,45,14
64 EDITTEXT IDEDIT_SERVERPORT,75,60,53,14,ES_NUMBER
65 COMBOBOX IDCOMBO_SERVERIP,75,28,82,400,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
66 PUSHBUTTON "启动",IDBUTTON_STARTSTOP,215,42,50,14
67 PUSHBUTTON "帮助",IDBUTTON_HELP,20,144,50,14
68END
69
70IDDIALOG_USER DIALOGEX 50, 50, 234, 109
71STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
72FONT 8, "MS Shell Dlg", 400, 0, 0x1
73BEGIN
74 DEFPUSHBUTTON "确定",IDBUTTON_OK,159,32,50,14
75 PUSHBUTTON "取消",IDBUTTON_CANCEL,159,60,50,14
76 LTEXT "昵称",IDSTATIC_NAME,22,24,20,10
77 LTEXT "账号",IDSTATIC_ID,22,48,20,10
78 LTEXT "密码",IDSTATIC_PSW,22,72,20,10
79 EDITTEXT IDEDIT_NAME,50,22,90,14,ES_AUTOHSCROLL
80 EDITTEXT IDEDIT_ID,50,46,90,14,ES_NUMBER
81 EDITTEXT IDEDIT_PSW,50,70,90,14,ES_NUMBER
82END
83
84
85/**//////////////////////////////////////////////////////////////////////////////
86//
87// DESIGNINFO
88//
89
90#ifdef APSTUDIO_INVOKED
91GUIDELINES DESIGNINFO
92BEGIN
93 IDDIALOG_SERVER, DIALOG
94 BEGIN
95 LEFTMARGIN, 7
96 RIGHTMARGIN, 309
97 TOPMARGIN, 7
98 BOTTOMMARGIN, 175
99 END
100
101 IDDIALOG_USER, DIALOG
102 BEGIN
103 LEFTMARGIN, 7
104 RIGHTMARGIN, 227
105 TOPMARGIN, 7
106 BOTTOMMARGIN, 102
107 END
108END
109#endif // APSTUDIO_INVOKED
110
111#endif // Chinese (Simplified, PRC) resources
112/**//////////////////////////////////////////////////////////////////////////////
113
114
115
116#ifndef APSTUDIO_INVOKED
117/**//////////////////////////////////////////////////////////////////////////////
118//
119// Generated from the TEXTINCLUDE 3 resource.
120//
121
122
123/**//////////////////////////////////////////////////////////////////////////////
124#endif // not APSTUDIO_INVOKED
125
126
serverDefaultInfo.h
1/**//*
2serverDefaultInfo.h
3服务器默认信息,如 PORT,ID 等
4*/
5
6
7#ifndef __SERVERDEFAULTINFO_H_INCLUDED__
8#define __SERVERDEFAULTINFO_H_INCLUDED__
9
10
11 // 默认服务器 PORT
12#define SERVER_PORT_DEFAULT 4096
13 // 默认服务器 ID (目前使用前10位)
14#define SERVER_ID_DEFAULT { 0,0,0,0,0,0,0,0,0,0,0,0 }
15
16
17#endif // __SERVERDEFAULTINFO_H_INCLUDED__
18
serverThreadCenter.cpp
1/**//*
2serverThreadCenter.cpp
3实现 CServerThreadCenter
4管理服务器线程通信,线程同步,线程局部数据,用户在线情况
5*/
6
7
8#include "serverThreadCenter.h"
9#include "threadCmd.h"
10
11
12CServerThreadCenter::CServerThreadCenter() {
13 ::InitializeCriticalSection( &(this->csOnline) );
14 ::InitializeCriticalSection( &(this->csUsed) );
15}
16
17CServerThreadCenter::~CServerThreadCenter() {
18 ::DeleteCriticalSection( &(this->csUsed) );
19 ::DeleteCriticalSection( &(this->csOnline) );
20}
21
22 // alloc [ (init) logon (use) logout ] free
23R32 CServerThreadCenter::alloc( PtrCServerThreadData &pData, SOCKET sk, const SOCKADDR_IN &addr, CServer *pServer ) {
24 U32 i;
25 R32 res = RERR;
26 for ( i = 0; ( res != ROK ) && ( i < SERVER_THREAD_MAX ); ++i ) {
27 if ( this->threadData[ i ].bUsed ) {
28 continue;
29 }
30 ::EnterCriticalSection( &(this->threadData[ i ].csAll) );
31 if ( !(this->threadData[ i ].bUsed) ) {
32 res = ROK;
33 pData = &(this->threadData[ i ]);
34 // 所有数据重新初始化
35 pData->bUsed = BTRUE;
36 pData->sock = sk;
37 pData->addr = addr;
38 pData->pServer = pServer;
39 pData->uCmd = TC_EMPTY;
40 pData->bSendLocked = BFALSE;
41 pData->bOnline = BFALSE;
42 ::EnterCriticalSection( &(this->csUsed) );
43 ++(this->totUsed);
44 ::LeaveCriticalSection( &(this->csUsed) );
45 }
46 ::LeaveCriticalSection( &(this->threadData[ i ].csAll) );
47 }
48 return res;
49}
50
51R32 CServerThreadCenter::free( PtrCServerThreadData pData ) {
52 R32 res = RERR;
53 ::EnterCriticalSection( &(pData->csAll) );
54 if ( (pData->bUsed) && (!(pData->bOnline)) ) {
55 res = ROK;
56 pData->bUsed = BFALSE;
57 ::EnterCriticalSection( &(this->csUsed) );
58 --(this->totUsed);
59 ::LeaveCriticalSection( &(this->csUsed) );
60 }
61 ::LeaveCriticalSection( &(pData->csAll) );
62 return res;
63}
64
65R32 CServerThreadCenter::logon( PtrCServerThreadData pData, const CUserId &id ) {
66 R32 res = RERR;
67 ::EnterCriticalSection( &(pData->csAll) );
68 if ( (pData->bUsed) && (!(pData->bOnline)) ) {
69 res = ROK;
70 pData->bOnline = BTRUE;
71 pData->id = id;
72 ::EnterCriticalSection( &(this->csOnline) );
73 ++(this->totOnline);
74 ::LeaveCriticalSection( &(this->csOnline) );
75 }
76 ::LeaveCriticalSection( &(pData->csAll) );
77 return res;
78}
79
80 // 不考虑发送绑定,alloc 重新初始化保证数据一致,发送方动态检查是否在线
81R32 CServerThreadCenter::logout( PtrCServerThreadData pData ) {
82 R32 res = RERR;
83 ::EnterCriticalSection( &(pData->csAll) );
84 if ( (pData->bUsed) && (pData->bOnline) ) {
85 res = ROK;
86 pData->bOnline = BFALSE;
87 ::EnterCriticalSection( &(this->csOnline) );
88 --(this->totOnline);
89 ::LeaveCriticalSection( &(this->csOnline) );
90 }
91 ::LeaveCriticalSection( &(pData->csAll) );
92 return res;
93}
94
95U32 CServerThreadCenter::getNumOnline() const {
96 return this->totOnline;
97}
98
99R32 CServerThreadCenter::sendAllCmd( U32 cmd, B32 ignPrevNotRecv ) {
100 U32 i;
101 R32 res = ROK;
102 for ( i = 0; i < SERVER_THREAD_MAX; ++i ) {
103 if ( this->threadData[ i ].bUsed ) {
104 ::EnterCriticalSection( &(this->threadData[ i ].csAll) );
105 if ( this->threadData[ i ].bUsed ) {
106 if ( this->threadData[ i ].uCmd != TC_EMPTY ) {
107 if ( ignPrevNotRecv ) {
108 this->threadData[ i ].uCmd = cmd;
109 }
110 else {
111 res = RERR;
112 }
113 }
114 else {
115 this->threadData[ i ].uCmd = cmd;
116 }
117 }
118 ::LeaveCriticalSection( &(this->threadData[ i ].csAll) );
119 }
120 }
121 return res;
122}
123
124R32 CServerThreadCenter::sendLock( const CUserId &id, PtrCServerThreadData &pData ) {
125 R32 res = RERR;
126 U32 i;
127 B32 find;
128 for ( i = 0; ( res != ROK ) && ( i < SERVER_THREAD_MAX ); ++i ) {
129 pData = &(this->threadData[ i ]);
130 if ( pData->bUsed ) {
131 ::EnterCriticalSection( &(pData->csAll) );
132 find = ( pData->bUsed ) && ( pData->bOnline ) && ( pData->id == id );
133 if ( find ) {
134 while ( find && (pData->bSendLocked) ) {
135 ::LeaveCriticalSection( &(pData->csAll) );
136 ::Sleep( 16 );
137 ::EnterCriticalSection( &(pData->csAll) );
138 find = ( pData->bUsed ) && ( pData->bOnline ) && ( pData->id == id );
139 }
140 if ( find && (!(pData->bSendLocked)) ) {
141 res = ROK;
142 pData->bSendLocked = BTRUE;
143 }
144 }
145 ::LeaveCriticalSection( &(pData->csAll) );
146 }
147 }
148 return res;
149}
150
151R32 CServerThreadCenter::sendUnlock( PtrCServerThreadData pData ) {
152 R32 res = RERR;
153 ::EnterCriticalSection( &(pData->csAll) );
154 if ( (pData->bUsed) && (pData->bOnline) && (pData->bSendLocked) ) {
155 res = ROK;
156 pData->bSendLocked = BFALSE;
157 }
158 ::LeaveCriticalSection( &(pData->csAll) );
159 return res;
160}
161
serverThreadCenter.h
1/**//*
2serverThreadCenter.h
3定义 CServerThreadCenter(线程安全)
4管理服务器线程通信,线程同步,线程局部数据,用户在线情况
5*/
6
7
8#ifndef __SERVERTHREADCENTER_H_INCLUDED__
9#define __SERVERTHREADCENTER_H_INCLUDED__
10
11
12#include "doubleLove.h"
13#include "serverThreadData.h"
14
15
16 // 最多同时在线用户数量
17#define ONLINE_NUM_MAX 10
18 // 服务线程最大数量(一个分发线程为一个用户服务,一个监听线程;
19 // 分发线程启动后才判断是否同时在线用户过多需拒绝登录)
20#define SERVER_THREAD_MAX (ONLINE_NUM_MAX+256)
21
22
23class CServerThreadCenter
24{
25public :
26 CServerThreadCenter();
27 ~CServerThreadCenter();
28
29 // alloc [ (init) logon (use) logout ] free
30 R32 alloc( PtrCServerThreadData &pData, SOCKET sk, const SOCKADDR_IN &addr, CServer *pServer );
31 R32 free( PtrCServerThreadData pData );
32 R32 logon( PtrCServerThreadData pData, const CUserId &id );
33 R32 logout( PtrCServerThreadData pData );
34 U32 getNumOnline() const;
35 R32 sendAllCmd( U32 cmd, B32 ignPrevNotRecv = BTRUE ); // 是否忽略命令缓冲区中未被处理的命令
36 // 在线用户发送绑定,保证独占对某一用户发送数据,保证一个完整包发送完成
37 // 对不在线的用户(不管是否已建立连接)绑定将失败
38 R32 sendLock( const CUserId &id, PtrCServerThreadData &pData );
39 R32 sendUnlock( PtrCServerThreadData pData );
40
41private :
42 CServerThreadData threadData[ SERVER_THREAD_MAX ];
43 U32 totOnline, totUsed;
44 mutable CRITICAL_SECTION csUsed, csOnline;
45};
46
47
48#endif // __SERVERTHREADCENTER_H_INCLUDED__
49
serverThreadData.cpp
1/**//*
2serverThreadData.cpp
3实现 CServerThreadData
4单一服务器线程的 命令,局部数据,及辅助功能函数
5*/
6
7
8#include "serverThreadData.h"
9#include "threadCmd.h"
10
11
12CServerThreadData::CServerThreadData() {
13 ::InitializeCriticalSection( &(this->csAll) );
14 this->bOnline = BFALSE;
15 this->bSendLocked = BFALSE;
16 this->bUsed = BFALSE;
17 this->pServer = NULL;
18 this->sock = INVALID_SOCKET;
19 this->uCmd = TC_EMPTY;
20}
21
22CServerThreadData::~CServerThreadData() {
23 ::DeleteCriticalSection( &(this->csAll) );
24}
25
26R32 CServerThreadData::getId( CUserId &id ) const {
27 R32 res = RERR;
28 ::EnterCriticalSection( &(this->csAll) );
29 if ( (this->bUsed) && (this->bOnline) ) {
30 res = ROK;
31 id = this->id;
32 }
33 ::LeaveCriticalSection( &(this->csAll) );
34 return res;
35}
36
37R32 CServerThreadData::getSocket( SOCKET &sk ) const {
38 R32 res = RERR;
39 ::EnterCriticalSection( &(this->csAll) );
40 if ( this->bUsed ) {
41 res = ROK;
42 sk = this->sock;
43 }
44 ::LeaveCriticalSection( &(this->csAll) );
45 return res;
46}
47
48R32 CServerThreadData::getServer( CServer* &p ) const {
49 R32 res = RERR;
50 ::EnterCriticalSection( &(this->csAll) );
51 if ( this->bUsed ) {
52 res = ROK;
53 p = this->pServer;
54 }
55 ::LeaveCriticalSection( &(this->csAll) );
56 return res;
57}
58
59R32 CServerThreadData::getCmd( U32 &cmd ) {
60 R32 res = RERR;
61 ::EnterCriticalSection( &(this->csAll) );
62 if ( this->bUsed ) {
63 cmd = this->uCmd;
64 if ( this->uCmd != TC_EMPTY ) {
65 res = ROK;
66 }
67 this->uCmd = TC_EMPTY;
68 }
69 ::LeaveCriticalSection( &(this->csAll) );
70 return res;
71}
72
73R32 CServerThreadData::getAddr( SOCKADDR_IN &addr ) const {
74 R32 res = RERR;
75 ::EnterCriticalSection( &(this->csAll) );
76 if ( this->bUsed ) {
77 res = ROK;
78 addr = this->addr;
79 }
80 ::LeaveCriticalSection( &(this->csAll) );
81 return res;
82}
83
84B32 CServerThreadData::isOnline() const {
85 B32 res = BFALSE;
86 ::EnterCriticalSection( &(this->csAll) );
87 res = ( (this->bUsed) && (this->bOnline) );
88 ::LeaveCriticalSection( &(this->csAll) );
89 return res;
90}
91
serverThreadData.h
1/**//*
2serverThreadData.h
3定义 CServerThreadData(线程安全)
4单一服务器线程的 命令,局部数据,及辅助功能函数
5*/
6
7
8#ifndef __SERVERTHREADDATA_H_INCLUDED__
9#define __SERVERTHREADDATA_H_INCLUDED__
10
11
12#include "doubleLove.h"
13#include "user.h"
14
15
16class CServer;
17class CServerThreadCenter;
18
19
20class CServerThreadData
21{
22public :
23 CServerThreadData();
24 ~CServerThreadData();
25
26 R32 getId( CUserId &id ) const;
27 R32 getSocket( SOCKET &sk ) const;
28 R32 getServer( CServer* &p ) const;
29 R32 getCmd( U32 &cmd );
30 R32 getAddr( SOCKADDR_IN &addr ) const;
31 B32 isOnline() const;
32
33 friend class CServerThreadCenter;
34
35private :
36 U32 uCmd;
37 B32 bUsed, bOnline, bSendLocked;
38 CUserId id;
39 SOCKET sock;
40 SOCKADDR_IN addr;
41 CServer *pServer;
42 mutable CRITICAL_SECTION csAll;
43};
44
45
46typedef CServerThreadData *PtrCServerThreadData;
47
48
49#endif // __SERVERTHREADDATA_H_INCLUDED__
50
threadCmd.h
1/**//*
2threadCmd.h
3服务器中各线程,客户端中各线程 通信命令
4*/
5
6
7#ifndef __THREADCMD_H_INCLUDED__
8#define __THREADCMD_H_INCLUDED__
9
10
11 // 空命令
12#define TC_EMPTY 10
13 // 服务器停止运行
14#define TC_SERVERSTOPPED 20
15 // 客户端停止运行
16#define TC_CLIENTSTOPPED 30
17 // 收到命令应答
18#define TC_YESSIR 40
19
20
21#endif // __THREADCMD_H_INCLUDED__
22
toolSz.cpp
1/**//*
2toolSz.cpp
3Sz 辅助工具
4*/
5
6
7#include "toolSz.h"
8
9
10Sz16 getSz16fromSz08( Sz16 sz16, cSz08 sz08, U32 maxCharNum ) {
11 U32 i;
12 if ( (sz16==NULL) || (sz08==NULL) ) {
13 return NULL;
14 }
15 for ( i = 0; (i<maxCharNum) && (sz08[ i ]); ++i ) {
16 sz16[ i ] = sz08[ i ];
17 }
18 sz16[ i ] = 0;
19 return sz16;
20}
21
22Sz16 getSz16fromU32( Sz16 sz, U32 num, U32 scale, U32 maxCharNum ) {
23 if ( (sz==NULL) || (scale<2) || (36<scale) ) {
24 return NULL;
25 }
26 if ( maxCharNum == 0 ) {
27 sz[ 0 ] = 0;
28 return sz;
29 }
30 if ( num == 0 ) {
31 sz[ 0 ] = T16('0');
32 sz[ 1 ] = 0;
33 return sz;
34 }
35
36 U32 i = 0, j = 0;
37 while ( (num>0) && (i<maxCharNum) ) {
38 sz[ i ] = (C16)( ( num % scale ) + ((U32)(T16('0'))) );
39 if ( sz[ i ] > T16('9') ) {
40 sz[ i ] = (C16)( ((U32)(sz[ i ])) - ((U32)(T16('0'))) + ((U32)(T16('A'))) );
41 }
42 num /= scale;
43 ++i;
44 }
45 sz[ i ] = 0;
46 --i;
47 while ( j < i ) {
48 C16 t = sz[ j ];
49 sz[ j ] = sz[ i ];
50 sz[ i ] = t;
51 ++j;
52 --i;
53 }
54 return sz;
55}
56
57Sz16 copySz16( Sz16 szDest, cSz16 szSrc, U32 maxCharNum ) {
58 U32 i;
59 if ( (szDest==NULL) || (szSrc==NULL) ) {
60 return NULL;
61 }
62 for ( i = 0; (i<maxCharNum) && (szSrc[ i ]); ++i ) {
63 szDest[ i ] = szSrc[ i ];
64 }
65 szDest[ i ] = 0;
66 return szDest;
67}
68
69I32 compareSz16( cSz16 a, cSz16 b, U32 maxCharNum ) {
70 U32 i;
71 if ( (a==NULL) || (b==NULL) ) {
72 return 0;
73 }
74 for ( i = 0; (i<maxCharNum) && (a[i]) && (b[i]); ++i ) {
75 if ( a[ i ] > b[ i ] ) {
76 return 1;
77 }
78 if ( a[ i ] < b[ i ] ) {
79 return (-1);
80 }
81 }
82 if ( i == maxCharNum ) {
83 return 0;
84 }
85 if ( a[ i ] ) {
86 return 1;
87 }
88 if ( b[ i ] ) {
89 return (-1);
90 }
91 return 0;
92}
93
94B32 isSz16AllazAZ( cSz16 sz ) {
95 cPc16 p;
96 for ( p = sz; (*p); ++p ) {
97 if ( (T16('a')<=(*p))&&((*p)<=T16('z')) ) {
98 continue;
99 }
100 if ( (T16('A')<=(*p))&&((*p)<=T16('Z')) ) {
101 continue;
102 }
103 return BFALSE;
104 }
105 return BTRUE;
106}
107
108R32 toSz16lowercase( Sz16 sz ) {
109 Pc16 p;
110 for ( p = sz; (*p); ++p ) {
111 if ( (T16('a')<=(*p))&&((*p)<=T16('z')) ) {
112 continue;
113 }
114 if ( (T16('A')<=(*p))&&((*p)<=T16('Z')) ) {
115 *p = (*p) - T16('A') + T16('a');
116 continue;
117 }
118 return RERR;
119 }
120 return ROK;
121}
122
123U32 lengthSz16( cSz16 sz ) {
124 if ( sz == NULL ) {
125 return 0;
126 }
127 U32 i;
128 for ( i = 0; sz[ i ]; ++i ) {
129 }
130 return i;
131}
132
133Sz16 getSz16fromU08Arr( Sz16 sz, const U08 *num, U32 numLen, U32 scale, C16 sep, U32 maxCharNum ) {
134 if ( (sz==NULL) || (num==NULL) || (numLen==0) || (scale<2) || (36<scale) || (maxCharNum==0) ) {
135 return NULL;
136 }
137 const U32 BUF_LEN = 32;
138 C16 buf[ BUF_LEN + 4 ];
139 U32 j = 0, i, bufLen;
140 for ( i = 0; (i < numLen) && (j < maxCharNum); ++i ) {
141 ::getSz16fromU32( buf, num[ i ], scale, BUF_LEN );
142 bufLen = ::lengthSz16( buf );
143 if ( j + bufLen <= maxCharNum ) {
144 ::copySz16( sz+j, buf, BUF_LEN );
145 j += bufLen;
146 }
147 if ( j < maxCharNum ) {
148 sz[ j++ ] = sep;
149 }
150 }
151 sz[ j ] = 0;
152 return sz;
153}
154
toolSz.h
1/**//*
2toolSz.h
3Sz 辅助工具
4*/
5
6
7#ifndef __TOOLSZ_H_INCLUDED__
8#define __TOOLSZ_H_INCLUDED__
9
10
11#include "doubleLove.h"
12
13
14template< class T, class K >
15I32 compareArray( const T *a, const K *b, U32 num ) {
16 U32 i;
17 if ( (a==NULL) || (b==NULL) ) {
18 return 0;
19 }
20 for ( i = 0; i < num; ++i ) {
21 if ( a[ i ] > b[ i ] ) {
22 return 1;
23 }
24 if ( a[ i ] < b[ i ] ) {
25 return (-1);
26 }
27 }
28 return 0;
29}
30
31template< class T, class K >
32T* copyArray( T *dest, const K *src, U32 num ) {
33 U32 i;
34 if ( (dest==NULL) || (src==NULL) ) {
35 return NULL;
36 }
37 for ( i = 0; i < num; ++i ) {
38 dest[ i ] = (T)(src[ i ]);
39 }
40 return dest;
41}
42
43template< class T, class K >
44T* copyArrayEnd( T *dest, const K *src, U32 num, K end ) {
45 U32 i;
46 if ( (dest==NULL) || (src==NULL) ) {
47 return NULL;
48 }
49 for ( i = 0; i < num; ++i ) {
50 dest[ i ] = src[ i ];
51 }
52 dest[ num ] = end;
53 return dest;
54}
55
56
57 // 不考虑编码转换,失败返回 NULL,最多转换前 maxCharNum 个字符
58Sz16 getSz16fromSz08( Sz16 sz16, cSz08 sz08, U32 maxCharNum );
59 // 无符号数字转换为 scale (2..36) 进制字符串,失败返回 NULL,成功返回目标串
60 // 大于十进制的字母大写,最多转换低位 maxCharNum 个字符
61Sz16 getSz16fromU32( Sz16 sz, U32 num, U32 scale, U32 maxCharNum );
62 // 简单复制,失败返回 NULL, 成功返回 目标串,最多复制前 maxCharNum 个字符
63Sz16 copySz16( Sz16 szDest, cSz16 szSrc, U32 maxCharNum );
64 // 简单比较,-1 小于,0 等于,1 大于,最多比较前 maxCharNum 个字符
65I32 compareSz16( cSz16 a, cSz16 b, U32 maxCharNum );
66 // 是否整个字符串由 a..zA..Z 构成
67B32 isSz16AllazAZ( cSz16 sz );
68 // 全部大写子母变小写
69R32 toSz16lowercase( Sz16 sz );
70 // 字符串长度
71U32 lengthSz16( cSz16 sz );
72 // 将无符号数字数组转换为字符串
73Sz16 getSz16fromU08Arr( Sz16 sz, const U08 *num, U32 numLen, U32 scale, C16 sep, U32 maxCharNum );
74
75
76#endif // __TOOLSZ_H_INCLUDED__
77
user.cpp
1/**//*
2user.cpp
3实现 CUserName, CUserId, CUserPsw
4用户相关
5*/
6
7
8#include "user.h"
9#include "toolSz.h"
10
11
12// CUserName
13CUserName::CUserName() {
14 this->d[ 0 ] = 0;
15}
16
17B32 CUserName::operator<( const CUserName &b ) const {
18 return ( ::compareSz16( this->d, b.d, USER_NAME_LEN_MAX ) < 0 );
19}
20
21B32 CUserName::operator==( const CUserName &b ) const {
22 return ( ::compareSz16( this->d, b.d, USER_NAME_LEN_MAX ) == 0 );
23}
24
25B32 CUserName::operator!=( const CUserName &b ) const {
26 return ( ::compareSz16( this->d, b.d, USER_NAME_LEN_MAX ) != 0 );
27}
28
29CUserName& CUserName::operator=( const CUserName &b ) {
30 ::copySz16( this->d, b.d, USER_NAME_LEN_MAX );
31 return (*this);
32}
33
34CUserName& CUserName::operator=( cSz16 sz ) {
35 ::copySz16( this->d, sz, USER_NAME_LEN_MAX );
36 return (*this);
37}
38
39CUserName& CUserName::operator=( cSz08 sz ) {
40 ::getSz16fromSz08( this->d, sz, USER_NAME_LEN_MAX );
41 return (*this);
42}
43
44R32 CUserName::getSz16( Sz16 sz ) const {
45 ::copySz16( sz, this->d, USER_NAME_LEN_MAX );
46 return ROK;
47}
48
49
50// CUserId
51CUserId::CUserId( const U08 *p ) {
52 ::copyArray( this->d, p, USER_ID_LEN );
53}
54
55B32 CUserId::operator<( const CUserId &b ) const {
56 return ( ::compareArray( this->d, b.d, USER_ID_LEN ) < 0 );
57}
58
59B32 CUserId::operator==( const CUserId &b ) const {
60 return ( ::compareArray( this->d, b.d, USER_ID_LEN ) == 0 );
61}
62
63B32 CUserId::operator!=( const CUserId &b ) const {
64 return ( ::compareArray( this->d, b.d, USER_ID_LEN ) != 0 );
65}
66
67CUserId& CUserId::operator=( const CUserId &b ) {
68 ::copyArray( this->d, b.d, USER_ID_LEN );
69 return (*this);
70}
71
72CUserId& CUserId::operator=( const U08 *p ) {
73 ::copyArray( this->d, p, USER_ID_LEN );
74 return (*this);
75}
76
77R32 CUserId::getU08( U08 *p ) const {
78 return ( ( ::copyArray( p, this->d, USER_ID_LEN ) != NULL ) ? ROK : RERR );
79}
80
81
82// CUserPsw
83CUserPsw::CUserPsw( const U08 *p ) {
84 ::copyArray( this->d, p, USER_PSW_LEN );
85}
86
87B32 CUserPsw::operator<( const CUserPsw &b ) const {
88 return ( ::compareArray( this->d, b.d, USER_PSW_LEN ) < 0 );
89}
90
91B32 CUserPsw::operator==( const CUserPsw &b ) const {
92 return ( ::compareArray( this->d, b.d, USER_PSW_LEN ) == 0 );
93}
94
95B32 CUserPsw::operator!=( const CUserPsw &b ) const {
96 return ( ::compareArray( this->d, b.d, USER_PSW_LEN ) != 0 );
97}
98
99CUserPsw& CUserPsw::operator=( const CUserPsw &b ) {
100 ::copyArray( this->d, b.d, USER_PSW_LEN );
101 return (*this);
102}
103
104CUserPsw& CUserPsw::operator=( const U08 *p ) {
105 ::copyArray( this->d, p, USER_PSW_LEN );
106 return (*this);
107}
108
109R32 CUserPsw::getU08( U08 *p ) const {
110 return ( ( ::copyArray( p, this->d, USER_PSW_LEN ) != NULL ) ? ROK : RERR );
111}
112
user.h
1/**//*
2user.h
3定义 CUserName, CUserId, CUserPsw(非线程安全)
4用户相关
5*/
6
7
8#ifndef __USER_H_INCLUDED__
9#define __USER_H_INCLUDED__
10
11
12#include "doubleLove.h"
13
14
15 // 用户名称最大字符数(不含 '\0')
16#define USER_NAME_LEN_MAX 16
17 // 用户 ID 数字个数
18#define USER_ID_LEN 10
19 // 用户密码数字个数
20#define USER_PSW_LEN 10
21
22
23class CUserName
24{
25public :
26 CUserName();
27 B32 operator<( const CUserName &b ) const;
28 B32 operator==( const CUserName &b ) const;
29 B32 operator!=( const CUserName &b ) const;
30 CUserName& operator=( const CUserName &b );
31 CUserName& operator=( cSz16 sz );
32 CUserName& operator=( cSz08 sz );
33 R32 getSz16( Sz16 sz ) const;
34private :
35 C16 d[ USER_NAME_LEN_MAX + 4 ];
36};
37
38class CUserId
39{
40public :
41 CUserId( const U08 *p = NULL );
42 B32 operator<( const CUserId &b ) const;
43 B32 operator==( const CUserId &b ) const;
44 B32 operator!=( const CUserId &b ) const;
45 CUserId& operator=( const CUserId &b );
46 CUserId& operator=( const U08 *p );
47 R32 getU08( U08 *p ) const;
48private :
49 U08 d[ USER_ID_LEN + 2 ];
50};
51
52class CUserPsw
53{
54public :
55 CUserPsw( const U08 *p = NULL );
56 B32 operator<( const CUserPsw &b ) const;
57 B32 operator==( const CUserPsw &b ) const;
58 B32 operator!=( const CUserPsw &b ) const;
59 CUserPsw& operator=( const CUserPsw &b );
60 CUserPsw& operator=( const U08 *p );
61 R32 getU08( U08 *p ) const;
62private :
63 U08 d[ USER_PSW_LEN + 2 ];
64};
65
66
67class CUser
68{
69public :
70 CUserName name;
71 CUserId id;
72 CUserPsw psw;
73};
74
75
76#endif // __USER_H_INCLUDED__
77
客户端:
(部分代码与服务器端共用)
client.cpp
1/**//*
2client.cpp
3实现 CClient 及相关线程
4客户端功能,无关界面
5*/
6
7
8#include "client.h"
9#include "threadCmd.h"
10#include "packetCmd.h"
11#include "serverDefaultInfo.h"
12#include "toolSz.h"
13#include <process.h>
14#include <string.h>
15
16
17#pragma comment( lib, "ws2_32.lib" )
18
19
20 // 对 CClientThreadData 的内容,只使用,不管理
21static unsigned __stdcall dealRecv( void *pParam ) {
22#ifdef DEBUG
23 // ::MessageBox( NULL, TEXT("开始 "), TEXT("dealRecv()"), MB_OK );
24#endif
25 PtrCClientThreadData pData = (PtrCClientThreadData)pParam;
26 SOCKET skSrc = INVALID_SOCKET;
27 U32 threadCmd = TC_EMPTY;
28 CPacket packet;
29 R32 res = ROK;
30 while ( res == ROK ) {
31 while ( ( pData->getCmd( threadCmd ) != ROK ) && ( res == ROK ) ) {
32 res = pData->getSocket( skSrc );
33 if ( res != ROK ) {
34 continue;
35 }
36 res = packet.recv( skSrc );
37#ifdef DEBUG
38 // ::MessageBox( NULL, TEXT("packet.recv() 之后 "), TEXT("dealRecv()"), MB_OK );
39#endif
40 if ( res != ROK ) {
41 continue; // 忽略失败
42 }
43 do {
44 if ( res != ROK ) {
45 ::Sleep( 20 );
46 }
47 res = pData->pushBack( packet );
48 } while ( ( res != ROK ) && ( pData->getCmd( threadCmd ) != ROK ) );
49#ifdef DEBUG
50 // ::MessageBox( NULL, TEXT("pData->pushBack() 之后 "), TEXT("dealRecv()"), MB_OK );
51#endif
52 if ( res != ROK ) {
53 break;
54 }
55 }
56 switch ( threadCmd ) {
57 case TC_EMPTY :
58 break;
59 case TC_CLIENTSTOPPED :
60 pData->writeCmd( TC_YESSIR, BTRUE );
61 res = RERR;
62 break;
63 default :
64 res = RERR;
65 break;
66 }
67 }
68#ifdef DEBUG
69 // ::MessageBox( NULL, TEXT("结束 "), TEXT("dealRecv()"), MB_OK );
70#endif
71 pData->markExit();
72 return 0;
73}
74
75 // 对 CClientThreadData 的内容,只使用,不管理
76static unsigned __stdcall dealSend( void *pParam ) {
77#ifdef DEBUG
78 // ::MessageBox( NULL, TEXT("开始 "), TEXT("dealSend()"), MB_OK );
79#endif
80 PtrCClientThreadData pData = (PtrCClientThreadData)pParam;
81 SOCKET skDest = INVALID_SOCKET;
82 U32 threadCmd = TC_EMPTY;
83 CPacket packet;
84 R32 res = ROK;
85 while ( res == ROK ) {
86 while ( ( pData->getCmd( threadCmd ) != ROK ) && ( res == ROK ) ) {
87 do {
88 if ( res != ROK ) {
89 ::Sleep( 20 );
90 }
91 res = pData->popFront( packet );
92 } while ( ( res != ROK ) && ( pData->getCmd( threadCmd ) != ROK ) );
93#ifdef DEBUG
94 // ::MessageBox( NULL, TEXT("pData->popFront() 之后 "), TEXT("dealSend()"), MB_OK );
95#endif
96 if ( res != ROK ) {
97 break;
98 }
99 res = pData->getSocket( skDest );
100 if ( res != ROK ) {
101 continue;
102 }
103 packet.send( skDest ); // 忽略失败
104#ifdef DEBUG
105 //::MessageBox( NULL, TEXT("packet.send() 之后 "), TEXT("dealSend()"), MB_OK );
106#endif
107 }
108 switch ( threadCmd ) {
109 case TC_EMPTY :
110 break;
111 case TC_CLIENTSTOPPED :
112 pData->writeCmd( TC_YESSIR, BTRUE );
113 res = RERR;
114 break;
115 default :
116 res = RERR;
117 break;
118 }
119 }
120#ifdef DEBUG
121 // ::MessageBox( NULL, TEXT("结束 "), TEXT("dealSend()"), MB_OK );
122#endif
123 pData->markExit();
124 return 0;
125}
126
127
128CClient::CClient() {
129 U08 serverid[] = SERVER_ID_DEFAULT;
130 this->idServer = serverid;
131 ::memset( &(this->addrServer), 0, sizeof(this->addrServer) );
132 this->addrServer.sin_family = AF_INET;
133 this->addrServer.sin_port = ::htons( SERVER_PORT_DEFAULT );
134 this->addrServer.sin_addr.S_un.S_addr = ::inet_addr( "127.0.0.1" );
135 this->skServer = INVALID_SOCKET;
136
137 this->state = SC_STOP;
138}
139
140CClient::~CClient() {
141 if ( this->state != SC_STOP ) {
142 this->logout();
143 }
144}
145
146
147R32 CClient::logon() {
148 if ( this->state != SC_STOP ) {
149 return ROK;
150 }
151 R32 res = RERR;
152 do {
153 WSADATA wsa;
154 if ( ::WSAStartup( MAKEWORD(2,2), &wsa ) ) {
155 break;
156 }
157 this->skServer = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
158 if ( this->skServer == INVALID_SOCKET ) {
159 ::WSACleanup();
160 break;
161 }
162 if ( ::connect( this->skServer, (const sockaddr*)(&(this->addrServer)), sizeof(this->addrServer) ) ) {
163 ::closesocket( this->skServer );
164 this->skServer = INVALID_SOCKET;
165 ::WSACleanup();
166 break;
167 }
168
169 U08 body[ USER_PSW_LEN ];
170 this->pswClient.getU08( body );
171 CPacket packet;
172 packet.build( this->idServer, this->idClient, PC_LOGON, USER_PSW_LEN, body );
173 packet.send( this->skServer );
174 packet.recv( this->skServer );
175 U32 cmd;
176 packet.parse( NULL, NULL, &cmd, NULL, NULL, 0, NULL );
177 if ( cmd != PC_LOGON_OK ) {
178 ::closesocket( this->skServer );
179 this->skServer = INVALID_SOCKET;
180 ::WSACleanup();
181 break;
182 }
183
184 this->threadRecv.clear();
185 this->threadRecv.writeSocket( this->skServer );
186 ::_beginthreadex( NULL, 0, dealRecv, (void*)(&(this->threadRecv)), 0, NULL );
187 this->threadSend.clear();
188 this->threadSend.writeSocket( this->skServer );
189 ::_beginthreadex( NULL, 0, dealSend, (void*)(&(this->threadSend)), 0, NULL );
190
191 res = ROK;
192 this->state = SC_ONLINE;
193 } while ( BFALSE );
194 return res;
195}
196
197R32 CClient::logout() {
198 if ( this->state == SC_STOP ) {
199 return ROK;
200 }
201 CPacket packet;
202 packet.build( this->idServer, this->idClient, PC_LOGOUT, 0, NULL );
203 this->sendOnePacket( packet );
204 ::Sleep( 32 );
205 this->threadRecv.writeCmd( TC_CLIENTSTOPPED, BTRUE );
206 this->threadSend.writeCmd( TC_CLIENTSTOPPED, BTRUE );
207 ::closesocket( this->skServer ); // recv, send 为阻塞工作
208 this->skServer = INVALID_SOCKET;
209 while ( ! this->threadRecv.hasExit() ) {
210 ::Sleep( 32 );
211 }
212 while ( ! this->threadSend.hasExit() ) {
213 ::Sleep( 32 );
214 }
215 ::WSACleanup();
216 this->state = SC_STOP;
217 return ROK;
218}
219
220
221R32 CClient::initClientId( const CUserId &id ) {
222 if ( this->state != SC_STOP ) {
223 return RERR;
224 }
225 this->idClient = id;
226 return ROK;
227}
228
229R32 CClient::initClientPsw( const CUserPsw &psw ) {
230 if ( this->state != SC_STOP ) {
231 return RERR;
232 }
233 this->pswClient = psw;
234 return ROK;
235}
236
237R32 CClient::initServerPort( U16 port ) {
238 if ( this->state != SC_STOP ) {
239 return RERR;
240 }
241 this->addrServer.sin_port = ::htons( port );
242 return ROK;
243}
244
245R32 CClient::initServerIp( U32 ip ) {
246 if ( this->state != SC_STOP ) {
247 return RERR;
248 }
249 this->addrServer.sin_addr.S_un.S_addr = ip;
250 return ROK;
251}
252
253
254R32 CClient::listHostIp( U32 *ipList, U32 &ipNum, U32 maxIpNum ) {
255 if ( this->state != SC_STOP ) {
256 return RERR;
257 }
258 R32 res = RERR;
259 do {
260 WSADATA wsa;
261 if ( ::WSAStartup( MAKEWORD(2,2), &wsa ) ) {
262 break;
263 }
264 C08 name[ 512 ];
265 PHOSTENT host;
266 if ( ::gethostname( name, 512 ) ) {
267 ::WSACleanup();
268 break;
269 }
270 host = ::gethostbyname( name );
271 if ( host == NULL ) {
272 ::WSACleanup();
273 break;
274 }
275 IN_ADDR addr;
276 for ( ipNum = 0; ( ipNum < maxIpNum ) && ( host->h_addr_list[ ipNum ] != NULL ); ++ipNum ) {
277 ::memcpy( &addr, host->h_addr_list[ ipNum ], host->h_length );
278 ipList[ ipNum++ ] = addr.S_un.S_addr;
279 }
280 ::WSACleanup();
281 res = ROK;
282 } while ( BFALSE );
283 return res;
284}
285
286
287R32 CClient::modPsw( const CUserPsw &pswNew ) {
288 if ( this->state != SC_ONLINE ) {
289 return RERR;
290 }
291 this->pswClientNew = pswNew;
292 U08 body[ USER_PSW_LEN*2 ];
293 this->pswClient.getU08( body );
294 this->pswClientNew.getU08( body+USER_PSW_LEN );
295 CPacket packet;
296 packet.build( this->idServer, this->idClient, PC_MODPSW, USER_PSW_LEN*2, body );
297 this->sendOnePacket( packet );
298 return ROK;
299}
300
301R32 CClient::sendData( const CUserId &idDest, U32 len, const U08 *pData ) {
302 if ( this->state != SC_ONLINE ) {
303 return RERR;
304 }
305 CPacket packet;
306 if ( ROK != packet.build( idDest, this->idClient, PC_DATA, len, pData ) ) {
307 return RERR;
308 }
309 return this->sendOnePacket( packet );
310}
311
312R32 CClient::recvOnePacket( CPacket &packet ) {
313 if ( this->state == SC_STOP ) {
314 return RERR;
315 }
316 R32 res = this->threadRecv.popFront( packet );
317 if ( res != ROK ) {
318 return res;
319 }
320 U32 cmd;
321 CUserId id;
322 packet.parse( NULL, &id, &cmd, NULL, NULL, 0, NULL );
323 if ( ( cmd == PC_MODPSW_OK ) && ( id == this->idServer ) ) {
324 this->pswClient = this->pswClientNew;
325 }
326 return ROK;
327}
328
329R32 CClient::sendCmd( U32 c ) {
330 if ( this->state == SC_STOP ) {
331 return RERR;
332 }
333 CPacket packet;
334 packet.build( this->idServer, this->idClient, c, 0, NULL );
335 return this->sendOnePacket( packet );
336}
337
338R32 CClient::sendOnePacket( const CPacket &packet ) {
339 if ( this->state == SC_STOP ) {
340 return RERR;
341 }
342 return this->threadSend.pushBack( packet );
343}
344
client.h
1/**//*
2client.h
3定义 CClient (非 线程安全)
4客户端功能,无关界面
5*/
6
7
8#ifndef __CLIENT_H_INCLUDED__
9#define __CLIENT_H_INCLUDED__
10
11
12#include "doubleLove.h"
13#include "user.h"
14#include "packet.h"
15#include "clientThreadData.h"
16
17
18 // 客户端运行状态
19 // 已经停止
20#define SC_STOP 0
21 // 已启动,未登录
22#define SC_RUNNING 10
23 // 用户在线
24#define SC_ONLINE 20
25
26
27// SOCKET 自己集中管理,客户端线程只使用,不管理
28
29class CClient
30{
31public :
32 CClient();
33 ~CClient();
34
35 R32 logon(); // 确认是否成功
36 // 析构之前必须调用此函数,以通知客户端线程,否则客户端线程会访问已经析构的成员类
37 // 等待客户端线程结束,方可退出,方可再次启动
38 R32 logout(); // 尝试确认是否成功
39
40 R32 initClientId( const CUserId &id );
41 CUserId getClientId() const { return this->idClient; }
42 CUserId getServerId() const { return this->idServer; }
43 R32 initClientPsw( const CUserPsw &psw );
44 CUserPsw getClientPsw() const { return this->pswClient; }
45 // 端口,本机字节序
46 R32 initServerPort( U16 port );
47 U16 getServerPort() const { return ::ntohs( this->addrServer.sin_port ); }
48 // IPv4, IN_ADDR 格式
49 R32 initServerIp( U32 ip );
50 U32 getServerIp() const { return this->addrServer.sin_addr.S_un.S_addr; }
51
52 U32 getState() const { return this->state; }
53
54 // 列举 IPv4, IN_ADDR 格式
55 R32 listHostIp( U32 *ipList, U32 &ipNum, U32 maxIpNum );
56
57 // 非阻塞 向服务器请求修改密码
58 R32 modPsw( const CUserPsw &pswNew );
59 // 非阻塞 向其他用户发送数据
60 R32 sendData( const CUserId &idDest, U32 len, const U08 *pData );
61 // 非阻塞 接收一个数据包(对于部分命令,会自动处理,但是不过滤)
62 R32 recvOnePacket( CPacket &packet );
63 // 发送一个无附加参数的命令
64 R32 sendCmd( U32 c );
65
66private :
67 R32 sendOnePacket( const CPacket &packet );
68
69 SOCKADDR_IN addrServer;
70 SOCKET skServer;
71 CUserId idServer, idClient;
72 CUserPsw pswClient;
73 U32 state;
74
75 CClientThreadData threadRecv;
76 CClientThreadData threadSend;
77
78 CUserPsw pswClientNew;
79};
80
81
82#endif // __CLIENT_H_INCLUDED__
83
client_gui.cpp
1/**//*
2client_gui.cpp
3客户端 图形界面
4*/
5
6
7#include "doubleLove.h"
8#include "client.h"
9#include "serverDefaultInfo.h"
10#include "toolSz.h"
11#include "code.h"
12#include "packetCmd.h"
13#include "resource.h"
14#include <CommCtrl.h>
15
16
17CClient client;
18HINSTANCE hInstance;
19
20const U32 IP_NUM_MAX = 512;
21U32 ipList[ IP_NUM_MAX ];
22U32 ipNum = 0, ipSelIdx;
23
24const U32 SG_LEN_MAX = 8;
25C16 sg[ SG_LEN_MAX + 4 ];
26U32 sgLen = 0;
27
28
29#define ENABLE(c) ::EnableWindow( ::GetDlgItem(hDlg,c), TRUE )
30#define DISABLE(c) ::EnableWindow( ::GetDlgItem(hDlg,c), FALSE )
31
32
33 // 登录
34BOOL CALLBACK DlgLogonProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
35 const U32 SZ_LEN_MAX = 512;
36 static C16 sz[ SZ_LEN_MAX + 4 ];
37
38 const U32 ID_BUF_LEN = USER_ID_LEN + 4;
39 C16 idcbuf[ ID_BUF_LEN + 4 ];
40 U08 idbuf[ ID_BUF_LEN + 4 ];
41 U32 idlen;
42
43 const U32 PSW_BUF_LEN = USER_PSW_LEN + 4;
44 C16 pswcbuf[ PSW_BUF_LEN + 4 ];
45 U08 pswbuf[ PSW_BUF_LEN + 4 ];
46 U32 pswlen;
47
48 U32 i;
49 IN_ADDR addr;
50
51 switch ( uMsg ) {
52 case WM_INITDIALOG :
53 ::SetDlgItemInt( hDlg, IDEDIT_SERVERPORT, SERVER_PORT_DEFAULT, FALSE );
54 if ( (ROK!=client.listHostIp(ipList, ipNum, IP_NUM_MAX) ) || (ipNum==0) ) {
55 ::MessageBox( hDlg, TEXT("网络错误 doubleLove 客户端启动失败"), TEXT("错误"), MB_OK|MB_ICONERROR );
56 ::EndDialog( hDlg, 0 );
57 }
58 for ( i = 0; i < ipNum; ++i ) {
59 addr.S_un.S_addr = ipList[ i ];
60 ::getSz16fromSz08( sz, ::inet_ntoa(addr), SZ_LEN_MAX );
61 ::SendMessage( ::GetDlgItem(hDlg,IDCOMBO_CLIENTIP), CB_ADDSTRING, 0, (LPARAM)sz );
62 }
63 ipSelIdx = 0;
64 ::SendMessage( ::GetDlgItem(hDlg,IDCOMBO_CLIENTIP), CB_SETCURSEL, ipSelIdx, 0 );
65 addr.S_un.S_addr = client.getServerIp();
66 lParam = MAKEIPADDRESS( addr.S_un.S_un_b.s_b1, addr.S_un.S_un_b.s_b2, addr.S_un.S_un_b.s_b3, addr.S_un.S_un_b.s_b4 );
67 ::SendMessage( ::GetDlgItem(hDlg,IDIPADDRESS_SERVERIP), IPM_SETADDRESS, 0, lParam );
68
69#ifdef DEBUG
70 ::SetDlgItemText( hDlg, IDEDIT_ID, TEXT("1111111111") );
71 ::SetDlgItemText( hDlg, IDEDIT_PSW, TEXT("1111111111") );
72#endif
73 return TRUE;
74 case WM_COMMAND :
75 switch ( LOWORD(wParam) ) {
76 case IDBUTTON_LOGON :
77 idlen = ::GetDlgItemText( hDlg, IDEDIT_ID, idcbuf, ID_BUF_LEN );
78 pswlen = ::GetDlgItemText( hDlg, IDEDIT_PSW, pswcbuf, PSW_BUF_LEN );
79 if ( (idlen==USER_ID_LEN) && (pswlen==USER_PSW_LEN) ) {
80 UINT u;
81 BOOL res;
82 u = ::GetDlgItemInt( hDlg, IDEDIT_SERVERPORT, &res, FALSE );
83 if ( res && (u<=0xFFFF) ) {
84 ::copyArray( idbuf, idcbuf, USER_ID_LEN );
85 ::copyArray( pswbuf, pswcbuf, USER_PSW_LEN );
86#ifdef DEBUG
87 ::MessageBox( hDlg, pswcbuf, idcbuf, MB_OK );
88#endif
89 client.initClientId( idbuf );
90 client.initClientPsw( pswbuf );
91 DWORD ad;
92 ::SendMessage( ::GetDlgItem(hDlg,IDIPADDRESS_SERVERIP), IPM_GETADDRESS, 0, (LPARAM)(&ad) );
93 addr.S_un.S_un_b.s_b1 = FIRST_IPADDRESS(ad);
94 addr.S_un.S_un_b.s_b2 = SECOND_IPADDRESS(ad);
95 addr.S_un.S_un_b.s_b3 = THIRD_IPADDRESS(ad);
96 addr.S_un.S_un_b.s_b4 = FOURTH_IPADDRESS(ad);
97 client.initServerIp( addr.S_un.S_addr );
98
99 DISABLE(IDIPADDRESS_SERVERIP); DISABLE(IDCOMBO_CLIENTIP);
100 DISABLE(IDEDIT_SERVERPORT); DISABLE(IDEDIT_ID); DISABLE(IDEDIT_PSW);
101 DISABLE(IDBUTTON_LOGON); DISABLE(IDBUTTON_HELP); DISABLE(IDBUTTON_EXIT);
102 if ( ROK == client.logon() ) {
103 ::EndDialog( hDlg, 0 );
104 }
105 else {
106 ::MessageBox( hDlg, TEXT("登录失败"), TEXT("失败"), MB_OK|MB_ICONINFORMATION );
107 }
108 ENABLE(IDIPADDRESS_SERVERIP); ENABLE(IDCOMBO_CLIENTIP);
109 ENABLE(IDEDIT_SERVERPORT); ENABLE(IDEDIT_ID); ENABLE(IDEDIT_PSW);
110 ENABLE(IDBUTTON_LOGON); ENABLE(IDBUTTON_HELP); ENABLE(IDBUTTON_EXIT);
111 }
112 else {
113 ::MessageBox( hDlg, TEXT("端口号不合法"), TEXT("错误"), MB_OK|MB_ICONERROR );
114 }
115 }
116 else {
117 ::MessageBox( hDlg, TEXT("账号或密码格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
118 }
119 return TRUE;
120 case IDBUTTON_EXIT :
121 ::EndDialog( hDlg, 0 );
122 return TRUE;
123 case IDBUTTON_HELP :
124 ::MessageBox( hDlg, TEXT("账号为10个数字\n密码为10个数字\n\n"), TEXT("帮助"), MB_OK|MB_ICONINFORMATION );
125 return TRUE;
126 }
127 return TRUE;
128 case WM_CLOSE :
129 ::PostMessage( hDlg, WM_COMMAND, IDBUTTON_EXIT, 0 );
130 break;
131 }
132 return FALSE;
133}
134
135
136 // 修改密码
137BOOL CALLBACK DlgModpswProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
138 const U32 BUF_LEN = 28;
139 C16 buf[ BUF_LEN + 4 ];
140 U32 bufLen;
141
142 U08 psw[ BUF_LEN ];
143 CUserPsw pswOld, pswNew;
144
145 switch ( uMsg ) {
146 case WM_INITDIALOG :
147 return TRUE;
148 case WM_COMMAND :
149 switch ( LOWORD(wParam) ) {
150 case IDBUTTON_OK :
151 bufLen = ::GetDlgItemText( hDlg, IDEDIT_OLDPSW, buf, BUF_LEN );
152 if ( bufLen == USER_PSW_LEN ) {
153 ::copyArray( psw, buf, USER_PSW_LEN );
154 pswOld = psw;
155 bufLen = ::GetDlgItemText( hDlg, IDEDIT_NEWPSW, buf, BUF_LEN );
156 if ( bufLen == USER_PSW_LEN ) {
157 ::copyArray( psw, buf, USER_PSW_LEN );
158 pswNew = psw;
159 if ( pswOld == client.getClientPsw() ) {
160 client.modPsw( pswNew );
161 ::EndDialog( hDlg, 0 );
162 }
163 else {
164 ::MessageBox( hDlg, TEXT("原密码错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
165 }
166 }
167 else {
168 ::MessageBox( hDlg, TEXT("密码格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
169 }
170 }
171 else {
172 ::MessageBox( hDlg, TEXT("密码格式错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
173 }
174 return TRUE;
175 case IDBUTTON_CANCEL :
176 ::EndDialog( hDlg, 0 );
177 return TRUE;
178 }
179 return TRUE;
180 case WM_CLOSE :
181 ::PostMessage( hDlg, WM_COMMAND, IDBUTTON_CANCEL, 0 );
182 return FALSE;
183 }
184 return FALSE;
185}
186
187
188BOOL CALLBACK DlgSafeProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
189 const U32 BUF_LEN = 128;
190 static C16 buf[ BUF_LEN + 4 ];
191 static U32 bufLen;
192
193 switch ( uMsg ) {
194 case WM_INITDIALOG :
195 return TRUE;
196 case WM_COMMAND :
197 switch ( LOWORD(wParam) ) {
198 case IDBUTTON_OK :
199 bufLen = ::GetDlgItemText( hDlg, IDEDIT_STRATEGY, buf, BUF_LEN );
200 if ( isLegalStrategy( buf, bufLen ) ) {
201 if ( bufLen == 0 ) {
202 sg[ 0 ] = 0;
203 sgLen = 0;
204 }
205 else {
206 ::copySz16( sg, buf, bufLen + 2 );
207 sgLen = bufLen;
208 }
209 }
210 else {
211 ::MessageBox( hDlg, TEXT("策略不合法"), TEXT("错误"), MB_OK|MB_ICONERROR );
212 }
213 ::EndDialog( hDlg, 0 );
214 return TRUE;
215 case IDBUTTON_CANCEL :
216 ::EndDialog( hDlg, 0 );
217 return TRUE;
218 case IDBUTTON_HELP :
219 ::MessageBox( hDlg, TEXT("策略:\na 摩尔斯\nb 手机按键\nc QWE键盘码\nd 栅栏密码\ne 倒序"), TEXT("帮助"), MB_OK|MB_ICONINFORMATION );
220 return TRUE;
221 }
222 return TRUE;
223 case WM_CLOSE :
224 ::PostMessage( hDlg, WM_COMMAND, IDBUTTON_CANCEL, 0 );
225 return FALSE;
226 }
227 return FALSE;
228}
229
230 // 编辑控件子类化
231WNDPROC orgEditProc;
232LRESULT CALLBACK EditProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
233 switch ( uMsg ) {
234 case WM_KEYDOWN :
235 // case WM_CHAR :
236 // case WM_KEYUP :
237 if ( wParam == VK_RETURN ) {
238 ::CallWindowProc( orgEditProc, hWnd, WM_COMMAND, IDBUTTON_SEND, 0 );
239 }
240 }
241 return ::CallWindowProc( orgEditProc, hWnd, uMsg, wParam, lParam );
242}
243
244 // 主界面
245BOOL CALLBACK DlgClientProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
246 const U32 SZ_LEN_MAX = 4096;
247 static C16 sz[ SZ_LEN_MAX + 4 ];
248 static U32 szLen;
249
250 const U32 DATA_LEN = 4096 * 2;
251 static U08 data[ DATA_LEN ];
252 static U32 dataLen;
253
254 static CPacket packet;
255
256 const U32 ID_BUF_LEN = USER_ID_LEN + 4;
257 static U08 idbuf[ ID_BUF_LEN + 4 ];
258
259 static CUserId id;
260
261 IN_ADDR addr;
262 U32 cmd, i;
263
264 switch ( uMsg ) {
265 case WM_INITDIALOG :
266 orgEditProc = (WNDPROC)::GetWindowLong( ::GetDlgItem(hDlg,IDEDIT_INPUT), GWL_WNDPROC );
267 ::SetWindowLong( ::GetDlgItem(hDlg,IDEDIT_INPUT), GWL_WNDPROC, (LONG)EditProc );
268 addr.S_un.S_addr = client.getServerIp();
269 ::getSz16fromSz08( sz, ::inet_ntoa(addr), SZ_LEN_MAX );
270 ::SetDlgItemText( hDlg, IDEDIT_SERVERIP, sz );
271 ::SetDlgItemInt( hDlg, IDEDIT_SERVERPORT, client.getServerPort(), FALSE );
272 addr.S_un.S_addr = ipList[ ipSelIdx ];
273 ::getSz16fromSz08( sz, ::inet_ntoa(addr), SZ_LEN_MAX );
274 ::SetDlgItemText( hDlg, IDEDIT_CLIENTIP, sz );
275 client.getClientId().getU08( idbuf );
276 ::copyArrayEnd( sz, idbuf, USER_ID_LEN, (U08)0 );
277 ::SetDlgItemText( hDlg, IDEDIT_SRCID, sz );
278 ::SetTimer( hDlg, 0, 100, NULL );
279 return TRUE;
280 case WM_TIMER :
281 if ( ROK == client.recvOnePacket( packet ) ) {
282 packet.parse( NULL, &id, &cmd, &dataLen, data, DATA_LEN, NULL );
283 switch ( cmd ) {
284 case PC_DATA_ERR_NOTONLINE :
285 ::MessageBox( hDlg, TEXT("对方不在线"), TEXT("发送失败"), MB_OK|MB_ICONINFORMATION );
286 break;
287 case PC_LOGON_AGAIN :
288 ::MessageBox( hDlg, TEXT("此账号在另一地点登录,您被迫下线"), TEXT("错误"), MB_OK|MB_ICONINFORMATION );
289 break;
290 case PC_DATA :
291 ::copySz16( sz, T16("\r\n\r\nForm : "), 11 );
292 id.getU08( idbuf );
293 ::copyArray( sz+11, idbuf, USER_ID_LEN );
294 ::copySz16( sz+11+USER_ID_LEN, T16("\r\n"), 2 );
295 ::decode( sz+13+USER_ID_LEN, szLen, data, dataLen, sg, sgLen );
296 i = ::GetWindowTextLength( ::GetDlgItem(hDlg,IDEDIT_HISTORY) );
297 ::SendMessage( ::GetDlgItem(hDlg,IDEDIT_HISTORY), EM_SETSEL, i, i );
298 ::SendMessage( ::GetDlgItem(hDlg,IDEDIT_HISTORY), EM_REPLACESEL, FALSE, (LPARAM)sz );
299 break;
300 case PC_ERROR :
301 ::MessageBox( hDlg, TEXT("网络数据错误"), TEXT("错误"), MB_OK|MB_ICONINFORMATION );
302 break;
303 case PC_LOGOUT_OK :
304 ::MessageBox( hDlg, TEXT("成功退出"), TEXT("成功"), MB_OK|MB_ICONINFORMATION );
305 break;
306 case PC_MODPSW_OK :
307 ::MessageBox( hDlg, TEXT("修改密码成功"), TEXT("成功"), MB_OK|MB_ICONINFORMATION );
308 break;
309 case PC_SERVERSTOPPED :
310 ::MessageBox( hDlg, TEXT("服务器已关闭"), TEXT("错误"), MB_OK|MB_ICONINFORMATION );
311 break;
312 case PC_NUMONLINE_OK :
313 CPacket::getU32fromNetU08( i, data );
314 ::SetDlgItemInt( hDlg, IDEDIT_NUMONLINE, i, FALSE );
315 break;
316 }
317 }
318 else {
319 client.sendCmd( PC_NUMONLINE );
320 }
321 return TRUE;
322 case WM_COMMAND :
323 switch ( LOWORD(wParam) ) {
324 case IDBUTTON_SEND :
325 if ( USER_ID_LEN == ::GetDlgItemText( hDlg, IDEDIT_DESTID, sz, SZ_LEN_MAX ) ) {
326 ::copyArray( idbuf, sz, USER_ID_LEN );
327 id = idbuf;
328 if ( (szLen=::GetDlgItemText( hDlg, IDEDIT_INPUT, sz, SZ_LEN_MAX )) && isSz16AllazAZ(sz) ) {
329 ::toSz16lowercase( sz );
330 ::encode( data, dataLen, sz, szLen, sg, sgLen );
331 client.sendData( id, dataLen, data );
332 ::SetDlgItemText( hDlg, IDEDIT_INPUT, TEXT("") );
333 }
334 else {
335 ::MessageBox( hDlg, TEXT("请输入大小写英文字母"), TEXT("错误"), MB_OK|MB_ICONERROR );
336 }
337 }
338 else {
339 ::MessageBox( hDlg, TEXT("接收方账号错误"), TEXT("错误"), MB_OK|MB_ICONERROR );
340 }
341 return TRUE;
342 case IDBUTTON_HELP :
343 ::MessageBox( hDlg, TEXT("输入小写英文"), TEXT("帮助"), MB_OK|MB_ICONINFORMATION );
344 return TRUE;
345 case IDBUTTON_MODPSW :
346 ::DialogBoxParam( hInstance, MAKEINTRESOURCE(IDDIALOG_MODPSW), hDlg, DlgModpswProc, 0 );
347 return TRUE;
348 case IDBUTTON_SAFE :
349 ::DialogBoxParam( hInstance, MAKEINTRESOURCE(IDDIALOG_SAFE), hDlg, DlgSafeProc, 0 );
350 return TRUE;
351 case IDBUTTON_EXIT :
352 ::KillTimer( hDlg, 0 );
353 ::EndDialog( hDlg, 0 );
354 return TRUE;
355 }
356 return TRUE;
357 case WM_CLOSE :
358 ::PostMessage( hDlg, WM_COMMAND, IDBUTTON_EXIT, 0 );
359 return FALSE;
360 }
361 return FALSE;
362}
363
364
365 // 入口
366int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR szCmd, INT nShow ) {
367 hInstance = hInst;
368 ::DialogBoxParam( hInst, MAKEINTRESOURCE(IDDIALOG_LOGON), NULL, DlgLogonProc, 0 );
369 if ( client.getState() == SC_STOP ) {
370 return 0;
371 }
372 ::DialogBoxParam( hInst, MAKEINTRESOURCE(IDDIALOG_CLIENT), NULL, DlgClientProc, 0 );
373 client.logout();
374 return 0;
375}
376
client_gui.rc
1// Microsoft Visual C++ generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/**//////////////////////////////////////////////////////////////////////////////
7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/**//////////////////////////////////////////////////////////////////////////////
13#undef APSTUDIO_READONLY_SYMBOLS
14
15/**//////////////////////////////////////////////////////////////////////////////
16// Chinese (Simplified, PRC) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
19LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
20
21#ifdef APSTUDIO_INVOKED
22/**//////////////////////////////////////////////////////////////////////////////
23//
24// TEXTINCLUDE
25//
26
271 TEXTINCLUDE
28BEGIN
29 "resource.h\0"
30END
31
322 TEXTINCLUDE
33BEGIN
34 "#include ""afxres.h""\r\n"
35 "\0"
36END
37
383 TEXTINCLUDE
39BEGIN
40 "\r\n"
41 "\0"
42END
43
44#endif // APSTUDIO_INVOKED
45
46
47/**//////////////////////////////////////////////////////////////////////////////
48//
49// Dialog
50//
51
52IDDIALOG_LOGON DIALOGEX 0, 0, 316, 130
53STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
54CAPTION "doubleLove 客户端"
55FONT 8, "MS Shell Dlg", 400, 0, 0x1
56BEGIN
57 DEFPUSHBUTTON "登录",IDBUTTON_LOGON,230,45,50,14
58 PUSHBUTTON "退出",IDBUTTON_EXIT,230,95,50,14
59 LTEXT "服务器 IP",IDSTATIC_SERVERIP,20,21,40,8
60 CONTROL "",IDIPADDRESS_SERVERIP,"SysIPAddress32",WS_TABSTOP,75,18,100,14
61 LTEXT "服务器端口",IDSTATIC_SERVERPORT,191,21,40,8
62 EDITTEXT IDEDIT_SERVERPORT,243,18,40,14,ES_NUMBER
63 LTEXT "客户端 IP",IDSTATIC_CLIENTIP,20,46,40,8
64 COMBOBOX IDCOMBO_CLIENTIP,75,43,100,400,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
65 LTEXT "账号",IDSTATIC_ID,20,73,17,8
66 EDITTEXT IDEDIT_ID,65,70,100,14,ES_NUMBER
67 LTEXT "密码",IDSTATIC_PSW,20,99,17,8
68 EDITTEXT IDEDIT_PSW,65,96,100,14,ES_PASSWORD | ES_NUMBER
69 PUSHBUTTON "帮助",IDBUTTON_HELP,230,70,50,14
70END
71
72IDDIALOG_CLIENT DIALOGEX 0, 0, 316, 346
73STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
74CAPTION "doubleLove 客户端"
75FONT 8, "MS Shell Dlg", 400, 0, 0x1
76BEGIN
77 PUSHBUTTON "退出",IDBUTTON_EXIT,239,314,50,14
78 PUSHBUTTON "发送",IDBUTTON_SEND,247,257,50,14
79 LTEXT "服务器 IP",IDSTATIC_SERVERIP,7,289,43,8
80 EDITTEXT IDEDIT_HISTORY,7,7,302,186,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | ES_READONLY | WS_VSCROLL | NOT WS_TABSTOP
81 LTEXT "接收方账号",IDSTATIC_DESTID,7,203,43,8
82 EDITTEXT IDEDIT_DESTID,56,200,70,14,ES_NUMBER
83 LTEXT "自己账号",IDSTATIC_SRCID,202,203,35,8
84 EDITTEXT IDEDIT_SRCID,240,200,70,14,ES_READONLY
85 EDITTEXT IDEDIT_INPUT,7,219,302,27,ES_AUTOHSCROLL
86 LTEXT "在线人数",IDSTATIC_NUMONLINE,7,258,33,8
87 EDITTEXT IDEDIT_NUMONLINE,55,257,30,14,ES_READONLY | ES_NUMBER | NOT WS_TABSTOP
88 PUSHBUTTON "修改密码",IDBUTTON_MODPSW,111,257,50,14
89 EDITTEXT IDEDIT_SERVERIP,55,287,65,14,ES_READONLY
90 LTEXT "服务器端口",IDSTATIC_SERVERPORT,141,289,41,8
91 EDITTEXT IDEDIT_SERVERPORT,193,287,40,14,ES_READONLY
92 LTEXT "自己 IP",IDSTATIC_CLIENTIP,7,319,26,8
93 EDITTEXT IDEDIT_CLIENTIP,55,314,65,14,ES_AUTOHSCROLL | ES_READONLY
94 PUSHBUTTON "信息加密策略",IDBUTTON_SAFE,135,313,64,14
95 PUSHBUTTON "帮助",IDBUTTON_HELP,177,257,50,14
96END
97
98IDDIALOG_SAFE DIALOGEX 0, 0, 207, 82
99STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
100CAPTION "doubleLove 信息加密策略"
101FONT 8, "MS Shell Dlg", 400, 0, 0x1
102BEGIN
103 DEFPUSHBUTTON "确定",IDBUTTON_OK,18,44,50,14
104 PUSHBUTTON "帮助",IDBUTTON_HELP,86,44,41,14
105 LTEXT "策略",IDSTATIC_STRATEGY,26,17,28,8
106 EDITTEXT IDEDIT_STRATEGY,63,15,91,14,ES_LOWERCASE | ES_AUTOHSCROLL
107 PUSHBUTTON "取消",IDBUTTON_CANCEL,141,44,41,14
108END
109
110IDDIALOG_MODPSW DIALOGEX 0, 0, 228, 86
111STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
112CAPTION "修改密码"
113FONT 8, "MS Shell Dlg", 400, 0, 0x1
114BEGIN
115 DEFPUSHBUTTON "确定",IDBUTTON_OK,171,21,50,14
116 PUSHBUTTON "取消",IDBUTTON_CANCEL,171,48,50,14
117 LTEXT "旧密码",IDSTATIC_OLDPSW,7,20,25,8
118 LTEXT "新密码",IDSTATIC_NEWPSW,7,50,25,8
119 EDITTEXT IDEDIT_OLDPSW,40,17,110,14,ES_PASSWORD | ES_NUMBER
120 EDITTEXT IDEDIT_NEWPSW,40,47,110,14,ES_NUMBER
121END
122
123
124/**//////////////////////////////////////////////////////////////////////////////
125//
126// DESIGNINFO
127//
128
129#ifdef APSTUDIO_INVOKED
130GUIDELINES DESIGNINFO
131BEGIN
132 IDDIALOG_LOGON, DIALOG
133 BEGIN
134 LEFTMARGIN, 7
135 RIGHTMARGIN, 309
136 TOPMARGIN, 7
137 BOTTOMMARGIN, 123
138 END
139
140 IDDIALOG_CLIENT, DIALOG
141 BEGIN
142 LEFTMARGIN, 7
143 RIGHTMARGIN, 309
144 TOPMARGIN, 7
145 BOTTOMMARGIN, 339
146 HORZGUIDE, 200
147 HORZGUIDE, 257
148 HORZGUIDE, 287
149 END
150
151 IDDIALOG_SAFE, DIALOG
152 BEGIN
153 LEFTMARGIN, 7
154 RIGHTMARGIN, 200
155 TOPMARGIN, 7
156 BOTTOMMARGIN, 75
157 END
158
159 IDDIALOG_MODPSW, DIALOG
160 BEGIN
161 LEFTMARGIN, 7
162 RIGHTMARGIN, 221
163 TOPMARGIN, 7
164 BOTTOMMARGIN, 79
165 END
166END
167#endif // APSTUDIO_INVOKED
168
169#endif // Chinese (Simplified, PRC) resources
170/**//////////////////////////////////////////////////////////////////////////////
171
172
173
174#ifndef APSTUDIO_INVOKED
175/**//////////////////////////////////////////////////////////////////////////////
176//
177// Generated from the TEXTINCLUDE 3 resource.
178//
179
180
181/**//////////////////////////////////////////////////////////////////////////////
182#endif // not APSTUDIO_INVOKED
183
184
clientThreadData.cpp
1/**//*
2clientThreadData.cpp
3实现 CClientThreadData
4客户端收发数据缓冲区,收发线程数据及通信
5*/
6
7
8#include "clientThreadData.h"
9#include "threadCmd.h"
10#include "toolSz.h"
11
12
13CClientThreadData::CClientThreadData() {
14 ::InitializeCriticalSection( &(this->csAll) );
15 this->clear();
16}
17
18CClientThreadData::~CClientThreadData() {
19 ::DeleteCriticalSection( &(this->csAll) );
20}
21
22
23R32 CClientThreadData::clear() {
24 ::EnterCriticalSection( &(this->csAll) );
25 this->uCmd = TC_EMPTY;
26 this->sock = INVALID_SOCKET;
27 this->queHead = this->queTail = 0;
28 this->queFull = BFALSE;
29 this->bExit = BFALSE;
30 ::LeaveCriticalSection( &(this->csAll) );
31 return ROK;
32}
33
34
35R32 CClientThreadData::pushBack( const CPacket &packet ) {
36 R32 res = RERR;
37 ::EnterCriticalSection( &(this->csAll) );
38 if ( (this->queHead != this->queTail) || (!(this->queFull)) ) {
39 res = packet.get( this->quePacket[ this->queTail ], &(this->queLen[ this->queTail ]), PACKET_LEN_MAX );
40 if ( res == ROK ) {
41 this->queTail = ( this->queTail + 1 ) % PACKET_BUFFER_LEN_MAX;
42 if ( this->queTail == this->queHead ) {
43 this->queFull = BTRUE;
44 }
45#ifdef DEBUG
46 //{
47 // C16 sz[ 109 ];
48 // ::getSz16fromU32( sz, this->queHead, 10, 100 );
49 // ::MessageBox( NULL, sz, TEXT("queHead *::pushBack()"), MB_OK );
50 // ::getSz16fromU32( sz, this->queTail, 10, 100 );
51 // ::MessageBox( NULL, sz, TEXT("queTail *::pushBack()"), MB_OK );
52 //}
53#endif
54 }
55 }
56 ::LeaveCriticalSection( &(this->csAll) );
57#ifdef DEBUG
58 //if ( res == ROK ) {
59 // ::MessageBox( NULL, TEXT("结束 成功 "), TEXT("CClientThreadData::pushBack()"), MB_OK );
60 //}
61#endif
62 return res;
63}
64
65R32 CClientThreadData::popFront( CPacket &packet ) {
66 R32 res = RERR;
67 ::EnterCriticalSection( &(this->csAll) );
68 if ( (this->queHead != this->queTail) || (this->queFull) ) {
69 res = packet.set( this->queLen[ this->queHead ], this->quePacket[ this->queHead ] );
70 if ( res == ROK ) {
71 this->queHead = ( this->queHead + 1 ) % PACKET_BUFFER_LEN_MAX;
72 if ( this->queHead == this->queTail ) {
73 this->queFull = BFALSE;
74 }
75#ifdef DEBUG
76 //{
77 // C16 sz[ 109 ];
78 // ::getSz16fromU32( sz, this->queHead, 10, 100 );
79 // ::MessageBox( NULL, sz, TEXT("queHead *::popFront()"), MB_OK );
80 // ::getSz16fromU32( sz, this->queTail, 10, 100 );
81 // ::MessageBox( NULL, sz, TEXT("queTail *::popFront()"), MB_OK );
82 //}
83#endif
84 }
85 }
86 ::LeaveCriticalSection( &(this->csAll) );
87#ifdef DEBUG
88 //if ( res == ROK ) {
89 // ::MessageBox( NULL, TEXT("结束 成功 "), TEXT("CClientThreadData::popFront()"), MB_OK );
90 //}
91#endif
92 return res;
93}
94
95
96R32 CClientThreadData::getCmd( U32 &cmd ) {
97 R32 res = RERR;
98 ::EnterCriticalSection( &(this->csAll) );
99 cmd = this->uCmd;
100 if ( this->uCmd != TC_EMPTY ) {
101 res = ROK;
102 this->uCmd = TC_EMPTY;
103 }
104 ::LeaveCriticalSection( &(this->csAll) );
105 return res;
106}
107
108R32 CClientThreadData::getSocket( SOCKET &sk ) const {
109 R32 res = RERR;
110 ::EnterCriticalSection( &(this->csAll) );
111 sk = this->sock;
112 if ( this->sock != INVALID_SOCKET ) {
113 res = ROK;
114 }
115 ::LeaveCriticalSection( &(this->csAll) );
116 return res;
117}
118
119R32 CClientThreadData::peekCmd( U32 &cmd ) const {
120 R32 res = RERR;
121 ::EnterCriticalSection( &(this->csAll) );
122 cmd = this->uCmd;
123 if ( this->uCmd != TC_EMPTY ) {
124 res = ROK;
125 }
126 ::LeaveCriticalSection( &(this->csAll) );
127 return res;
128}
129
130
131R32 CClientThreadData::writeCmd( U32 cmd, B32 ignPrevNotRecv ) {
132 R32 res = RERR;
133 ::EnterCriticalSection( &(this->csAll) );
134 if ( this->uCmd == TC_EMPTY ) {
135 this->uCmd = cmd;
136 res = ROK;
137 }
138 else if ( ignPrevNotRecv ) {
139 this->uCmd = cmd;
140 res = ROK;
141 }
142 ::LeaveCriticalSection( &(this->csAll) );
143 return res;
144}
145
146R32 CClientThreadData::writeSocket( SOCKET sk ) {
147 ::EnterCriticalSection( &(this->csAll) );
148 this->sock = sk;
149 ::LeaveCriticalSection( &(this->csAll) );
150 return ROK;
151}
152
clientThreadData.h
1/**//*
2clientThreadData.h
3定义 CClientThreadData(线程安全)
4客户端收发数据缓冲区,收发线程数据及通信
5*/
6
7
8#ifndef __CLIENTTHREADDATA_H_INCLUDED__
9#define __CLIENTTHREADDATA_H_INCLUDED__
10
11
12#include "doubleLove.h"
13#include "packet.h"
14
15
16#define PACKET_BUFFER_LEN_MAX 128
17
18
19class CClientThreadData
20{
21public :
22 CClientThreadData();
23 ~CClientThreadData();
24
25 R32 clear();
26
27 R32 pushBack( const CPacket &packet );
28 R32 popFront( CPacket &packet );
29
30 R32 getCmd( U32 &cmd ); // 获取命令,并清除
31 R32 getSocket( SOCKET &sk ) const;
32 R32 peekCmd( U32 &cmd ) const; // 只读出命令
33
34 R32 writeCmd( U32 cmd, B32 ignPrevNotRecv = BTRUE ); // 是否忽略命令缓冲区中尚未处理的命令
35 R32 writeSocket( SOCKET sk );
36
37 void markExit() { this->bExit = BTRUE; }
38 B32 hasExit() const { return this->bExit; };
39
40private :
41 mutable CRITICAL_SECTION csAll;
42 U32 uCmd;
43 SOCKET sock;
44
45 U08 quePacket[ PACKET_BUFFER_LEN_MAX ][ PACKET_LEN_MAX ];
46 U32 queLen[ PACKET_BUFFER_LEN_MAX ];
47 U32 queHead, queTail;
48 B32 queFull;
49
50 B32 bExit;
51};
52
53
54typedef CClientThreadData *PtrCClientThreadData;
55
56
57#endif // __CLIENTTHREADDATA_H_INCLUDED__
58
code.cpp
1/**//*
2code.cpp
3编码解码
4*/
5
6
7#include "code.h"
8#include "toolSz.h"
9
10
11 // a 将数字串编码
12R32 encodeMorse( U08 *mor, U32 &morLen, const U08 *dig, U32 digLen ) {
13 static U08 morse[] = { 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x10, 0x18, 0x1C, 0x1E };
14 U32 i;
15 for ( i = 0; i < digLen; ++i ) {
16 if ( dig[ i ] > 9 ) {
17 return RERR;
18 }
19 mor[ i ] = morse[ dig[ i ] ];
20 }
21 morLen = digLen;
22#ifdef DEBUG
23 {
24 Pc16 sz = new C16[ morLen+morLen + 4 ];
25 ::getSz16fromU08Arr( sz, mor, morLen, 16, T16('-'), morLen+morLen );
26 ::MessageBox( NULL, sz, TEXT("莫尔斯编码"), MB_OK );
27 delete sz;
28 }
29#endif
30 return ROK;
31}
32
33 // 将莫尔斯串解码
34R32 decodeMorse( U08 *dig, U32 &digLen, const U08 *mor, U32 morLen ) {
35 static U08 morse[] = { 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x10, 0x18, 0x1C, 0x1E };
36 static U08 mm[ 0x100 ] = { 0 };
37 U32 i;
38 for ( i = 0; i < (sizeof(morse))/(sizeof(morse[0])); ++i ) {
39 mm[ morse[ i ] ] = i;
40 }
41 for ( i = 0; i < morLen; ++i ) {
42 dig[ i ] = mm[ mor[ i ] ];
43 if ( (dig[i]==0) && (mor[i]!=0x1F) ) {
44 return RERR;
45 }
46 }
47 digLen = morLen;
48#ifdef DEBUG
49 {
50 Pc16 sz = new C16[ digLen+digLen + 4 ];
51 ::getSz16fromU08Arr( sz, dig, digLen, 16, T16('-'), digLen+digLen );
52 ::MessageBox( NULL, sz, TEXT("莫尔斯编码"), MB_OK );
53 delete sz;
54 }
55#endif
56 return ROK;
57}
58
59
60 // b 手机
61R32 encodePhone( U08 *dig, U32 &digLen, cSz16 alp, U32 alpLen ) {
62 U32 i;
63 for( i = 0; i < alpLen; ++i ) {
64 if ( alp[ i ] < 's' ) {
65 dig[ 2 * i ] = ( alp[ i ] - 'a' ) / 3 + 2;
66 dig[ 2 * i + 1 ] = ( alp[ i ] - 'a' ) % 3 + 1;
67 }
68 else {
69 if ( alp[ i ] == 's' ) {
70 dig[ 2 * i ] = 7;
71 dig[ 2 * i + 1 ] = 4;
72 }
73 else {
74 if ( alp[ i ] == 'z' ){
75 dig[ 2 * i ] = 9;
76 dig[ 2 * i + 1 ] = 4;
77 }
78 else {
79 dig[ 2 * i ] = ( alp[ i ] - 'a' - 1 ) / 3 + 2;
80 dig[ 2 * i + 1 ] = ( alp[ i ] - 'a' - 1 ) % 3 + 1;
81 }
82 }
83 }
84 }
85 digLen = alpLen * 2;
86#ifdef DEBUG
87 {
88 Pc16 sz = new C16[ digLen+digLen + 4 ];
89 ::getSz16fromU08Arr( sz, dig, digLen, 16, T16('-'), digLen+digLen );
90 ::MessageBox( NULL, sz, TEXT("手机编码"), MB_OK );
91 delete sz;
92 }
93#endif
94 return ROK;
95}
96
97R32 decodePhone( Sz16 alp, U32 &alpLen, const U08 *dig, U32 digLen ) {
98 C08 p;
99 U32 i;
100 for ( i = 0; i < digLen; i+=2 ) {
101 p = ( dig[ i ] - 2 ) * 3 + dig[ i + 1 ] - 1;
102 if ( dig[ i ] > 7 ) {
103 ++p;
104 }
105 alp[ i / 2 ] = p + 'a';
106 }
107 alpLen = digLen / 2;
108 alp[ alpLen ] = 0;
109#ifdef DEBUG
110 ::MessageBox( NULL, alp, TEXT("手机解码"), MB_OK );
111#endif
112 return ROK;
113}
114
115 // c QWE
116R32 encodeQwe( Sz16 qwe, U32 &qweLen, cSz16 alp, U32 alpLen ) {
117 static C08 mm[] = T08("qwertyuiopasdfghjklzxcvbnm");
118 U32 i;
119 for ( i = 0; i < alpLen; ++i ) {
120 qwe[ i ] = mm[ alp[ i ] - 'a' ];
121 }
122 qweLen = alpLen;
123 qwe[ qweLen ] = 0;
124#ifdef DEBUG
125 ::MessageBox( NULL, qwe, TEXT("QWE 编码"), MB_OK );
126#endif
127 return ROK;
128}
129
130R32 decodeQwe( Sz16 alp, U32 &alpLen, cSz16 qwe, U32 qweLen ) {
131 static C08 mm[] = T08("kxvmcnophqrszyijadlegwbuft");
132 U32 i;
133 for ( i = 0; i < qweLen; ++i ) {
134 alp[ i ] = mm[ qwe[ i ] - 'a' ];
135 }
136 alpLen = qweLen;
137 alp[ alpLen ] = 0;
138#ifdef DEBUG
139 ::MessageBox( NULL, alp, TEXT("QWE 解码"), MB_OK );
140#endif
141 return ROK;
142}
143
144 // d 栅栏
145R32 encodeFence( Sz16 dest, U32 &destLen, cSz16 src, U32 srcLen, U32 n ) {
146 if ( n == 0 ) {
147 return RERR;
148 }
149 U32 i, j, k = 0;
150 for ( i = 0; i < n; ++i ) {
151 for ( j = i; j < srcLen; j += n ) {
152 dest[ k++ ] = src[ j ];
153 }
154 }
155 destLen = srcLen;
156 dest[ destLen ] = 0;
157#ifdef DEBUG
158 ::MessageBox( NULL, dest, TEXT("栅栏编码"), MB_OK );
159#endif
160 return ROK;
161}
162
163R32 decodeFence( Sz16 src, U32 &srcLen, cSz16 dest, U32 destLen, U32 n ) {
164 if ( n == 0 ) {
165 return RERR;
166 }
167 U32 i, j, k = 0, m = ( destLen + n - 1 ) / n;
168 for ( i = 0; i < m; ++i ) {
169 for ( j = i; j < destLen; j += m ) {
170 src[ k++ ] = dest[ j ];
171 }
172 }
173 srcLen = destLen;
174 src[ srcLen ] = 0;
175#ifdef DEBUG
176 ::MessageBox( NULL, src, TEXT("栅栏解码"), MB_OK );
177#endif
178 return ROK;
179}
180
181
182 // 倒序
183R32 encodeInv( Sz16 dest, U32 &destLen, cSz16 src, U32 srcLen ) {
184 U32 i;
185 for ( i = 0; i < srcLen; ++i ) {
186 dest[ i ] = src[ srcLen - 1 - i ];
187 }
188 destLen = srcLen;
189 dest[ destLen ] = 0;
190#ifdef DEBUG
191 ::MessageBox( NULL, dest, TEXT("倒序编码"), MB_OK );
192#endif
193 return ROK;
194}
195
196R32 decodeInv( Sz16 src, U32 &srcLen, cSz16 dest, U32 destLen ) {
197 U32 i;
198 for ( i = 0; i < destLen; ++i ) {
199 src[ i ] = dest[ destLen - 1 - i ];
200 }
201 srcLen = destLen;
202 src[ srcLen ] = 0;
203#ifdef DEBUG
204 ::MessageBox( NULL, src, TEXT("倒序解码"), MB_OK );
205#endif
206 return ROK;
207}
208
209
210B32 isLegalStrategy( cSz16 sg, U32 num ) {
211 if ( num == 0 ) {
212 return BTRUE;
213 }
214 if ( (num<2) || (8<num) || (sg[num-1]!=T16('a')) || (sg[num-2]!=T16('b')) ) {
215 return BFALSE;
216 }
217 U32 i;
218 for ( i = 0; i + 2 < num; ++i ) {
219 if ( (sg[i]==T16('a')) || (sg[i]==T16('b')) ) {
220 return BFALSE;
221 }
222 }
223 return BTRUE;
224}
225
226 // 使用一个编码策略编码
227R32 encode( U08 *mor, U32 &morLen, cSz16 sz, U32 szLen, cSz16 sg, U32 sgLen ) {
228 if ( sgLen == 0 ) {
229 ::copyArray( mor, sz, szLen ); // 对英文可以
230 morLen = szLen;
231 return ROK;
232 }
233
234 U32 i;
235 Sz16 szSrc = new C16[ szLen + szLen + 4 ];
236 Sz16 szDest = new C16[ szLen + szLen + 4 ];
237
238 U08 *mTmp = new U08[ szLen + szLen + 4 ];
239 U32 szSrcLen, szDestLen, mTmpLen;
240
241 ::copySz16( szSrc, sz, szLen );
242 szSrcLen = szLen;
243
244 for ( i = 0; i < sgLen; ++i ) {
245 switch ( sg[ i ] ) {
246 case T16('a') :
247 ::encodeMorse( mor, morLen, mTmp, mTmpLen );
248 break;
249 case T16('b') :
250 ::encodePhone( mTmp, mTmpLen, szSrc, szSrcLen );
251 break;
252 case T16('c') :
253 ::encodeQwe( szDest, szDestLen, szSrc, szSrcLen );
254 ::copyArray( szSrc, szDest, szDestLen );
255 szSrcLen = szDestLen;
256 break;
257 case T16('d') :
258 ::encodeFence( szDest, szDestLen, szSrc, szSrcLen, 2 );
259 ::copyArray( szSrc, szDest, szDestLen );
260 szSrcLen = szDestLen;
261 break;
262 case T16('e') :
263 ::encodeInv( szDest, szDestLen, szSrc, szSrcLen );
264 ::copyArray( szSrc, szDest, szDestLen );
265 szSrcLen = szDestLen;
266 break;
267 }
268 }
269
270 delete szSrc;
271 delete szDest;
272 delete mTmp;
273 return ROK;
274}
275
276 // 逆用一个编码策略解码
277R32 decode( Sz16 sz, U32 &szLen, const U08 *mor, U32 morLen, cSz16 sg, U32 sgLen ) {
278 if ( sgLen == 0 ) {
279 ::copyArray( sz, mor, morLen ); // 对英文可以
280 szLen = morLen;
281 return ROK;
282 }
283
284 I32 i;
285 Sz16 szSrc = new C16[ szLen + szLen + 4 ];
286 Sz16 szDest = new C16[ szLen + szLen + 4 ];
287
288 U08 *mTmp = new U08[ szLen + szLen + 4 ];
289 U32 szSrcLen, szDestLen, mTmpLen;
290
291 for ( i = sgLen; i > 0; ) {
292 --i;
293 switch ( sg[ i ] ) {
294 case T16('a') :
295 ::decodeMorse( mTmp, mTmpLen, mor, morLen );
296 break;
297 case T16('b') :
298 ::decodePhone( szSrc, szSrcLen, mTmp, mTmpLen );
299 break;
300 case T16('c') :
301 ::decodeQwe( szDest, szDestLen, szSrc, szSrcLen );
302 ::copyArray( szSrc, szDest, szDestLen );
303 szSrcLen = szDestLen;
304 break;
305 case T16('d') :
306 ::decodeFence( szDest, szDestLen, szSrc, szSrcLen, 2 );
307 ::copyArray( szSrc, szDest, szDestLen );
308 szSrcLen = szDestLen;
309 break;
310 case T16('e') :
311 ::decodeInv( szDest, szDestLen, szSrc, szSrcLen );
312 ::copyArray( szSrc, szDest, szDestLen );
313 szSrcLen = szDestLen;
314 break;
315 }
316 }
317
318 ::copySz16( sz, szSrc, szSrcLen );
319 szLen = szSrcLen;
320
321 delete szSrc;
322 delete szDest;
323 delete mTmp;
324 return ROK;
325}
326
code.h
1/**//*
2code.h
3编码解码
4*/
5
6
7#ifndef __CODE_H_INCLUDED__
8#define __CODE_H_INCLUDED__
9
10
11#include "doubleLove.h"
12
13
14// 假设函数输入合法
15
16
17 // a 将数字串编码
18R32 encodeMorse( U08 *mor, U32 &morLen, const U08 *dig, U32 digLen );
19 // 将莫尔斯串解码
20R32 decodeMorse( U08 *dig, U32 &digLen, const U08 *mor, U32 morLen );
21
22 // b 手机
23R32 encodePhone( U08 *dig, U32 &digLen, cSz16 alp, U32 alpLen );
24R32 decodePhone( Sz16 alp, U32 &alpLen, const U08 *dig, U32 digLen );
25
26 // c QWE
27R32 encodeQwe( Sz16 qwe, U32 &qweLen, cSz16 alp, U32 alpLen );
28R32 decodeQwe( Sz16 alp, U32 &alpLen, cSz16 qwe, U32 qweLen );
29
30 // d 栅栏
31R32 encodeFence( Sz16 dest, U32 &destLen, cSz16 src, U32 srcLen, U32 n );
32R32 decodeFence( Sz16 src, U32 &srcLen, cSz16 dest, U32 destLen, U32 n );
33
34 // 倒序
35R32 encodeInv( Sz16 dest, U32 &destLen, cSz16 src, U32 srcLen );
36R32 decodeInv( Sz16 src, U32 &srcLen, cSz16 dest, U32 destLen );
37
38 // 是否为合法加密序列
39B32 isLegalStrategy( cSz16 sg, U32 num );
40
41 // 使用一个编码策略编码
42R32 encode( U08 *mor, U32 &morLen, cSz16 sz, U32 szLen, cSz16 sg, U32 sgLen );
43 // 逆用一个编码策略解码
44R32 decode( Sz16 sz, U32 &szLen, const U08 *mor, U32 morLen, cSz16 sg, U32 sgLen );
45
46
47#endif // __CODE_H_INCLUDED__
48
debug.h
1/**//*
2debug.h
3调试开关,决定是否启用调试功能
4由宏 DEBUG 是否定义决定是否启动调试功能
5*/
6
7
8#ifndef __DEBUG_H_INCLUDED__
9#define __DEBUG_H_INCLUDED__
10
11
12#ifndef DEBUG
13// #define DEBUG
14#endif
15
16
17#endif // __DEBUG_H_INCLUDED__
18
resource.h
1//{{NO_DEPENDENCIES}}
2// Microsoft Visual C++ generated include file.
3// Used by client_gui.rc
4//
5#define IDDIALOG_LOGON 101
6#define IDDIALOG_CLIENT 102
7#define IDDIALOG_SAFE 103
8#define IDDIALOG_MODPSW 104
9#define IDBUTTON_LOGON 1001
10#define IDBUTTON_EXIT 1002
11#define IDSTATIC_SERVERIP 1003
12#define IDIPADDRESS_SERVERIP 1004
13#define IDSTATIC_SERVERPORT 1005
14#define IDEDIT_SERVERPORT 1006
15#define IDSTATIC_CLIENTIP 1007
16#define IDCOMBO_CLIENTIP 1008
17#define IDSTATIC_ID 1009
18#define IDEDIT_ID 1010
19#define IDSTATIC_PSW 1011
20#define IDEDIT_PSW 1012
21#define IDBUTTON_HELP 1013
22#define IDBUTTON_SEND 1015
23#define IDEDIT_HISTORY 1016
24#define IDSTATIC_DESTID 1017
25#define IDEDIT_DESTID 1018
26#define IDSTATIC_SRCID 1019
27#define IDEDIT_SRCID 1020
28#define IDEDIT_INPUT 1021
29#define IDSTATIC_NUMONLINE 1022
30#define IDEDIT_NUMONLINE 1023
31#define IDBUTTON_MODPSW 1024
32#define IDEDIT_SERVERIP 1025
33#define IDEDIT_CLIENTIP 1028
34#define IDBUTTON_SAFE 1029
35#define IDBUTTON_OK 1031
36#define IDSTATIC_STRATEGY 1032
37#define IDEDIT_STRATEGY 1033
38#define IDBUTTON_CANCEL 1034
39#define IDSTATIC_OLDPSW 1035
40#define IDSTATIC_NEWPSW 1036
41#define IDEDIT_OLDPSW 1037
42#define IDEDIT_NEWPSW 1038
43
44// Next default values for new objects
45//
46#ifdef APSTUDIO_INVOKED
47#ifndef APSTUDIO_READONLY_SYMBOLS
48#define _APS_NEXT_RESOURCE_VALUE 105
49#define _APS_NEXT_COMMAND_VALUE 40001
50#define _APS_NEXT_CONTROL_VALUE 1039
51#define _APS_NEXT_SYMED_VALUE 101
52#endif
53#endif
54