gpt4 book ai didi

ios - TCP 套接字在运行 iOS 10.3.2 的 iPhone 7 上不起作用

转载 作者:行者123 更新时间:2023-11-29 00:18:10 25 4
gpt4 key购买 nike

我正在创建一个通过 TCP 套接字 (NSStream) 与外部服务通信的应用。

我在运行 iOS 10.3.2 的 iPhone 7 上遇到问题,NSStream 拥塞,消息发送速度不够快,我的应用无法使用react.在 运行 iOS 10.3.2 的 iPhone 6s 或运行 iOS 9 的 iPhone 6没有问题。我已经在 两部运行 iOS 10.3.2 的 iPhone 7 上尝试过此操作,都有同样的问题

所以本质上,我每秒都会向我的外部设备发送多条请求消息。

例如: 如果我每秒向外部服务发送 3 条消息,则只有其中一条消息发送响应。我写了一个回调方法,只有当我从外部设备收到 ACK 时才会触发。我使用了 NSLogs 并且我发现请求实际上从未通过套接字发送,这让我相信这是一个 iOS 问题(Stream 在等待响应时是否被阻止发送额外的消息?)

这是我的 TCPSocketManager 类的代码,其中管理套接字连接(我在后台线程上发送请求,然后一旦响应返回,我就发送回调主线程):

@interface TCPSocketManager ()
@property (weak, nonatomic)NSMutableArray *jsonObject;
@property (weak, nonatomic)NSMutableArray *dataQueue;
@property (nonatomic)bool sentNotif;
@end

static NSString *hostIP;
static int hostPORT;
@implementation TCPSocketManager {
BOOL flag_canSendDirectly;
}

-(instancetype)initWithSocketHost:(NSString *)host withPort:(int)port{
hostIP = host;
hostPORT = port;

_completionDict = [NSMutableDictionary new];
_dataQueue = [NSMutableArray new];

CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(host), port, &readStream, &writeStream);

_inputStream = (__bridge NSInputStream *)readStream;
_outputStream = (__bridge NSOutputStream *)writeStream;

[self openStreams];
return self;
}

-(void)openStreams {
[_outputStream setDelegate:self];
[_inputStream setDelegate:self];

[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

[_outputStream open];
[_inputStream open];
}

-(void)closeStreams{
[_outputStream close];
[_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[_inputStream close];
[_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void) messageReceived:(NSString *)message {
[message enumerateLinesUsingBlock:^(NSString * _Nonnull msg, BOOL * _Nonnull stop) {
[_messages addObject:msg];

NSError *error;
NSMutableArray *copyJsonObject = [NSJSONSerialization JSONObjectWithData:[msg dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error];
_jsonObject = [copyJsonObject copy];

NSDictionary *rsp_type = [_jsonObject valueForKey:@"rsp"];
NSString *typeKey = rsp_type[@"type”];
CompleteMsgRsp response = _completionDict[typeKey];
//assign the response to the block

if (response){
dispatch_async(dispatch_get_main_queue(), ^{
response(rsp_type);
});
}

[_completionDict removeObjectForKey:typeKey]
}];
}

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
break;

case NSStreamEventHasBytesAvailable:
if (theStream == _inputStream){
uint8_t buffer[1024];
NSInteger len;

while ([_inputStream hasBytesAvailable])
{
len = [_inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output)
{
[self messageReceived:output];
//Do Something with the message
}
}
}
}
break;

case NSStreamEventHasSpaceAvailable:{
//send data over stream now that we know the stream is ready to send/ receive
[self _sendData];
break;
}
case NSStreamEventErrorOccurred:
[self initWithSocketHost:hostIP withPort:hostPORT];
break;

case NSStreamEventEndEncountered:
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

break;
default:
DLog(@"Unknown Stream Event");
}

}

- (void)sendData:(NSData *)data {
//insert the request to the head of a queue
[_dataQueue insertObject:data atIndex:0];

//if able to send directly, send it. This flag is set in _sendData if the array is empty
//Message is sent when the stream has space available.
if (flag_canSendDirectly) [self _sendData];
}

-(void)_sendData {
flag_canSendDirectly = NO;

//get the last object of the array.
NSData *data = [_dataQueue lastObject];

//if data is empty, set the send direct flag
if (data == nil){
flag_canSendDirectly = YES;
return;
}
//send request out over stream, store the amount of bytes written to stream
NSInteger bytesWritten = [_outputStream write:[data bytes] maxLength:[data length]];

//if bytes written is more than 0, we know something was output over the stream
if (bytesWritten >0) {
//remove the request from the queue.
[self.dataQueue removeLastObject];
}
}

- (void)sendRequest:(NSString*)request withCompletion:(void (^)(NSDictionary *rsp_dict))finishBlock{
self.uuid = [[NSUUID UUID] UUIDString];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//Convert the request string to NSData.
NSData *data = [[NSData alloc] initWithData:[request dataUsingEncoding:NSASCIIStringEncoding]];

//method to send the data over stream with a queue
[self sendData:data];

//Completion Handler for Messages
NSString *typeKey = reqType;
[_completionDict setObject:[finishBlock copy] forKey:typeKey];
});
}
@end

这是一个示例请求和 TCPSocketManager 类的定义:

-(void)connectToSocket{
_socketMan = [[TCPSocketManager alloc] initWithSocketHost:@"192.168.1.10" withPort:50505];
}

-(void)sendSomeRequest:(NSString *)request {
[_socketMan sendRequest:request withCompletion:^(NSDictionary *rsp_dict) {
NSString *result =[rsp_dict objectForKey:@"result"];
if ([result length] < 3 && [result isEqualToString:@"OK"]){
//Successful request with a response
}else{
//Request has failed with no/ bad response
}
}];
}

由于此问题只出现在 iPhone 7 设备上。我想知道这是否是 NSStream 错误? 有没有人遇到过任何类似的问题。使用诸如 CocoaAsyncSocket 之类的库会更好吗?有没有办法在不使用外部库的情况下解决这个问题?

我之前设置过 CocoaAsyncSocket 但它对我没有帮助,因为它破坏了消息请求和响应。它会在同一条消息中发回多个响应,从而在解析消息时增加更多的复杂性。

最佳答案

我在您的代码中发现了几个您应该尝试修复的问题。

  1. 您可以并发访问 _dataQueue 数组:您从另一个线程(使用全局队列)写入它,但在主线程上读取。

  2. 由于您在主线程上使用流,因此您应该避免像在处理 NSStreamEventHasBytesAvailable 事件时那样使用循环。只需将一些数据读入缓冲区并将其存储在 NSMutableString 中。

  3. 数据可能不完整,因此您应该手动检查您的缓冲区中是否有完整的行,如果是,就处理它。当您使用 enumerateLinesUsingBlock: 时,可能会有不完整的行,您会丢失该不完整的行。

关于ios - TCP 套接字在运行 iOS 10.3.2 的 iPhone 7 上不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44785303/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com