@@ -109,7 +109,7 @@ - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)t
109109
110110 // 处理消息
111111 switch (msgType) {
112- case TJPMessageTypeNormalData: // TJPMessageTypeNormalData
112+ case TJPMessageTypeNormalData: // 普通数据消息
113113 {
114114 if (self.didReceiveDataHandler ) {
115115 self.didReceiveDataHandler (payload, seq);
@@ -119,13 +119,61 @@ - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)t
119119 break ;
120120
121121
122- case TJPMessageTypeHeartbeat: // TJPMessageTypeHeartbeat
122+ case TJPMessageTypeHeartbeat: // 心跳消息
123123 {
124124 if (self.didReceiveDataHandler ) {
125125 self.didReceiveDataHandler (payload, seq);
126126 }
127127 [self sendHeartbeatACKForSequence: seq sessionId: sessionId toSocket: sock];
128128 }
129+ break ;
130+ case TJPMessageTypeControl: // 控制消息
131+ {
132+ if (self.didReceiveDataHandler ) {
133+ self.didReceiveDataHandler (payload, seq);
134+ }
135+ 136+ // 解析TLV数据,获取版本信息
137+ if (payload.length >= 12 ) {
138+ // Tag(2) + Length(4) + Value(2) + Flags(2)
139+ uint16_t tag;
140+ uint32_t length;
141+ uint16_t value;
142+ uint16_t flags;
143+ 144+ const void *bytes = payload.bytes ;
145+ memcpy (&tag, bytes, sizeof (uint16_t ));
146+ memcpy (&length, bytes + 2 , sizeof (uint32_t ));
147+ memcpy (&value, bytes + 6 , sizeof (uint16_t ));
148+ memcpy (&flags, bytes + 8 , sizeof (uint16_t ));
149+ 150+ // 转换网络字节序到主机字节序
151+ tag = ntohs (tag);
152+ length = ntohl (length);
153+ value = ntohs (value);
154+ flags = ntohs (flags);
155+ 156+ NSLog (@" [MOCK SERVER] 版本协商:Tag=%u , Length=%u , Value=0x%04X , Flags=0x%04X " ,
157+ tag, length, value, flags);
158+ 159+ if (tag == 0x0001 ) { // 版本标签
160+ uint8_t clientMajorVersion = (value >> 8 ) & 0xFF ;
161+ uint8_t clientMinorVersion = value & 0xFF ;
162+ 163+ NSLog (@" [MOCK SERVER] 客户端版本: %u .%u " , clientMajorVersion, clientMinorVersion);
164+ 165+ NSLog (@" [MOCK SERVER] 客户端特性: %@ " , [self featureDescriptionWithFlags: flags]);
166+ 167+ 168+ // 发送版本协商响应
169+ [self sendVersionNegotiationResponseForSequence: seq sessionId: sessionId clientVersion: value
170+ supportedFeatures: flags toSocket: sock];
171+ }
172+ }
173+ 174+ // 发送控制消息ACK
175+ [self sendControlACKForSequence: seq sessionId: sessionId toSocket: sock];
176+ }
129177
130178 break ;
131179
@@ -137,6 +185,18 @@ - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)t
137185 [sock readDataWithTimeout: -1 tag: 0 ];
138186}
139187
188+ - (NSString *)featureDescriptionWithFlags : (uint16_t )flags {
189+ NSMutableString *desc = [NSMutableString string ];
190+ 191+ if (flags & 0x0001 ) [desc appendString: @" 基本消息 " ];
192+ if (flags & 0x0002 ) [desc appendString: @" 加密 " ];
193+ if (flags & 0x0004 ) [desc appendString: @" 压缩 " ];
194+ if (flags & 0x0008 ) [desc appendString: @" 已读回执 " ];
195+ if (flags & 0x0010 ) [desc appendString: @" 群聊 " ];
196+ 197+ return desc.length > 0 ? desc : @" 无特性" ;
198+ }
199+ 140200- (void )socketDidDisconnect : (GCDAsyncSocket *)sock withError : (NSError *)err {
141201 [self .connectedSockets removeObject: sock];
142202}
@@ -171,6 +231,33 @@ - (void)sendACKForSequence:(uint32_t)seq sessionId:(uint16_t)sessionId toSocket:
171231 [socket writeData: ackData withTimeout: -1 tag: 0 ];
172232}
173233
234+ - (void )sendControlACKForSequence : (uint32_t )seq sessionId : (uint16_t )sessionId toSocket : (GCDAsyncSocket *)socket {
235+ NSLog (@" [MOCK SERVER] 收到控制消息,序列号: %u " , seq);
236+ 237+ // 使用当前时间戳
238+ uint32_t currentTime = (uint32_t )[[NSDate date ] timeIntervalSince1970 ];
239+ 240+ TJPFinalAdavancedHeader reply = {0 };
241+ reply.magic = htonl (kProtocolMagic );
242+ reply.version_major = kProtocolVersionMajor ;
243+ reply.version_minor = kProtocolVersionMinor ;
244+ reply.msgType = htons (TJPMessageTypeACK); // 仍然使用ACK类型,但可以考虑使用TJPMessageTypeControl
245+ reply.sequence = htonl (seq);
246+ reply.timestamp = htonl (currentTime);
247+ reply.encrypt_type = TJPEncryptTypeNone;
248+ reply.compress_type = TJPCompressTypeNone;
249+ reply.session_id = htons (sessionId);
250+ reply.bodyLength = 0 ;
251+ 252+ // 没有数据体,checksum设为0
253+ reply.checksum = 0 ;
254+ 255+ NSData *ackData = [NSData dataWithBytes: &reply length: sizeof (reply)];
256+ NSLog (@" [MOCK SERVER] 控制消息响应包字段:magic=0x%X , msgType=%hu , sequence=%u , timestamp=%u , sessionId=%hu " ,
257+ ntohl (reply.magic ), ntohs (reply.msgType ), ntohl (reply.sequence ), ntohl (reply.timestamp ), ntohs (reply.session_id ));
258+ [socket writeData: ackData withTimeout: -1 tag: 0 ];
259+ }
260+ 174261
175262- (void )sendHeartbeatACKForSequence : (uint32_t )seq sessionId : (uint16_t )sessionId toSocket : (GCDAsyncSocket *)socket {
176263 NSLog (@" [MOCK SERVER] 收到心跳包,序列号: %u " , seq);
@@ -200,6 +287,61 @@ - (void)sendHeartbeatACKForSequence:(uint32_t)seq sessionId:(uint16_t)sessionId
200287 [socket writeData: ackData withTimeout: -1 tag: 0 ];
201288}
202289
290+ - (void )sendVersionNegotiationResponseForSequence : (uint32_t )seq sessionId : (uint16_t )sessionId clientVersion : (uint16_t )clientVersion supportedFeatures : (uint16_t )features toSocket : (GCDAsyncSocket *)socket {
291+ NSLog (@" [MOCK SERVER] 收到控制消息,序列号: %u " , seq);
292+ 293+ // 使用当前时间戳
294+ uint32_t currentTime = (uint32_t )[[NSDate date ] timeIntervalSince1970 ];
295+ 296+ // 服务器选择的版本和功能
297+ uint8_t serverMajorVersion = kProtocolVersionMajor ;
298+ uint8_t serverMinorVersion = kProtocolVersionMinor ;
299+ uint16_t serverVersion = (serverMajorVersion << 8 ) | serverMinorVersion;
300+ uint16_t agreedFeatures = features & 0x0003 ; // 仅支持客户端请求的部分功能
301+ 302+ // 构建TLV数据
303+ NSMutableData *tlvData = [NSMutableData data ];
304+ 305+ // 版本协商响应TLV
306+ uint16_t versionResponseTag = htons (0x0002 ); // 响应标签
307+ uint32_t versionResponseLength = htonl (4 );
308+ uint16_t versionResponseValue = htons (serverVersion);
309+ uint16_t agreedFeaturesValue = htons (agreedFeatures);
310+ 311+ [tlvData appendBytes: &versionResponseTag length: sizeof (uint16_t )];
312+ [tlvData appendBytes: &versionResponseLength length: sizeof (uint32_t )];
313+ [tlvData appendBytes: &versionResponseValue length: sizeof (uint16_t )];
314+ [tlvData appendBytes: &agreedFeaturesValue length: sizeof (uint16_t )];
315+ 316+ // 计算校验和
317+ uint32_t checksum = [TJPNetworkUtil crc32ForData: tlvData];
318+ 319+ // 构建响应头
320+ TJPFinalAdavancedHeader responseHeader = {0 };
321+ responseHeader.magic = htonl (kProtocolMagic );
322+ responseHeader.version_major = serverMajorVersion;
323+ responseHeader.version_minor = serverMinorVersion;
324+ responseHeader.msgType = htons (TJPMessageTypeControl);
325+ responseHeader.sequence = htonl (seq + 1 ); // 响应序列号+1
326+ responseHeader.timestamp = htonl (currentTime);
327+ responseHeader.encrypt_type = TJPEncryptTypeNone;
328+ responseHeader.compress_type = TJPCompressTypeNone;
329+ responseHeader.session_id = htons (sessionId);
330+ responseHeader.bodyLength = htonl ((uint32_t )tlvData.length );
331+ responseHeader.checksum = htonl (checksum);
332+ 333+ // 构建完整响应
334+ NSMutableData *responseData = [NSMutableData dataWithBytes: &responseHeader
335+ length: sizeof (responseHeader)];
336+ [responseData appendData: tlvData];
337+ 338+ NSLog (@" [MOCK SERVER] 发送版本协商响应:服务器版本 %u .%u ,协商功能 0x%04X " ,
339+ serverMajorVersion, serverMinorVersion, agreedFeatures);
340+ 341+ [socket writeData: responseData withTimeout: -1 tag: 0 ];
342+ 343+ }
344+ 203345
204346// 旧方法 已废弃目前单元测试在用 后续移除
205347- (void )sendHeartbeatACKForSequence : (uint32_t )seq toSocket : (nonnull GCDAsyncSocket *)socket {
0 commit comments