Ассоциировать произвольную информацию с сокетом, используя GCDAyncSocket

Я создал простое клиент-серверное приложение с GCDAsyncSocket.

Хост транслирует свою услугу через Bonjour, клиенты подключаются к нему, затем каждый клиент отправляет хосту определенную информацию, после завершения запросов хостом он должен теперь иметь возможность отправлять каждый запрос соответствующему клиенту.

Здесь, когда клиент отключился (возможно, перезагрузил WiFi) до того, как он получил свой завершенный запрос и снова подключил его, подключенный хост и порт могут измениться.

поэтому для денитрификации клиентов я хочу сохранить список подключенных клиентов в словаре

key : vendorID (specific to each client and can't change)
value :  connected host and port (gcdAsyncSocket instance) 

Как я могу отправить произвольную информацию (vendorID) с сокетом?

кажется, что GCDAsyncSocket имеет свойство с именем UserData, я установил его с vendorID на клиенте, но на хосте это NULL.

клиент:

- (BOOL)connectWithService:(NSNetService *)service {
BOOL _isConnected = NO;

// Copy Service Addresses
NSArray *addresses = [[service addresses] mutableCopy];

if (!self.socket || ![self.socket isConnected]) {
    // Initialize Socket


       self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

        //adding deviceID to sockect to identify connected clients in the host

        self.socket.userData = @"vendorID2308746238764021";

        // Connect
        while (!_isConnected && [addresses count]) {
            NSData *address = [addresses objectAtIndex:0];
            NSError *error = nil;

            if ([self.socket connectToAddress:address error:&error]) {
                _isConnected = true;
            }

            else if (error) {
                NSLog(@"Unable to connect to address. Error %@ with user info %@.", error, [error userInfo]);
            }
        }

    } else {
        _isConnected = [self.socket isConnected];
    }

    return _isConnected;
}

Ведущий:

- (void)socket:(GCDAsyncSocket *)socket didAcceptNewSocket:(GCDAsyncSocket *)newSocket {
    NSLog(@"Accepted New Socket from %@:%hu", [newSocket connectedHost], [newSocket connectedPort]);

    //both userData is null!
    NSLog(@"%@",newSocket.userData);
    NSLog(@"%@",socket.userData);
    //adding new socket to the list of connected clients
    //using ip and port of the scoket as key
    [self.clients setObject:newSocket forKey:[NSString stringWithFormat:@"%@-%d", [newSocket connectedHost], [newSocket connectedPort]]];
    // Notify Delegate
    [self.delegate tcpHost:self didHostClientOnSocket:newSocket];
}

У кого-нибудь есть идеи, как мне решить этот вид обмена информацией между клиентом и хостом?

1 ответ

Решение

ClientSide: в моем классе TCPClient, когда клиент подключен к серверу, первый отправляемый мной пакет - это пакет идентификации:

//server can identify  device
- (void)sendIdentity
{
    NSData *identifcationData = [[UIDevice deviceID] dataUsingEncoding:NSUTF8StringEncoding];
    HAPacket *packet = [[HAPacket alloc] initWithData:identifcationData type:HAPacketTypeIdentity action:HAPacketActionUnknown];
    [self sendPacket:packet];
}

Сервер: получает этот пакет и идентифицирует клиента. В TCPHost: после подключения клиента я сохраняю его во временном массиве. в socket:didReadData Я проверяю:

if (tag == TAG_BODY) {

    //first packet is always for identifaction. if client has not identified, its id is empty
    Client *unknownClient = [[self.temp linq_where:^BOOL(Client *client)
                              {
                                  return client.ID == nil || [client.ID isEqualToString: @""];
                              }] linq_firstOrNil];

    if (unknownClient && (unknownClient.ID == nil || [unknownClient.ID  isEqualToString: @""])) {
        NSLog(@"identifying client...");
        [self identifyClient:unknownClient withData:data];
    }
    else
{
// parse the packet as usual
}
Другие вопросы по тегам