Как получить сообщения буфера протокола Google через сокетное соединение, не отключая клиента? - PullRequest
0 голосов
/ 08 июня 2010

Я пытаюсь отправить сообщение .proto из приложения iPhone на сервер Java через сокетное соединение.Однако до сих пор я сталкиваюсь с проблемой, когда речь идет о сервере, получающем данные;кажется, что он обрабатывается только после того, как клиентское соединение было разорвано.Это указывает на то, что данные отправляются, но сервер сохраняет свой входной поток открытым и ожидает дополнительных данных.Кто-нибудь знает, как я могу решить эту проблему?Текущий код (или, по крайней мере, соответствующие части) выглядит следующим образом:

iPhone:

Person *person = [[[[Person builder] setId:1] setName:@"Bob"] build];
RequestWrapper *request = [[[RequestWrapper builder] setPerson:person] build];
NSData *data = [request data];  
AsyncSocket *socket = [[AsyncSocket alloc] initWithDelegate:self];

if (![socket connectToHost:@"192.168.0.6" onPort:6666 error:nil]){
    [self updateLabel:@"Problem connecting to socket!"];
} else {
    [self updateLabel:@"Sending data to server..."];
    [socket writeData:data withTimeout:-1 tag:0];
    [self updateLabel:@"Data sent, disconnecting"];
    //[socket disconnect];
}

Java:

try {
        RequestWrapper wrapper = RequestWrapper.parseFrom(socket.getInputStream());
        Person person = wrapper.getPerson();
        if (person != null) {
            System.out.println("Persons name is " + person.getName());
            socket.close();
        }

При выполнении этого, кажется,зависание на строке, где RequestWrapper обрабатывает inputStream.Я попытался заменить метод сокета writedata на:

[request writeToOutputStream:[socket getCFWriteStream]];

(здесь я вызываю gpb для записи в выходной поток вместо записи данных, генерируемых в выходной поток)

Я думаю, что это может сработать, однако я получаю сообщение об ошибке, утверждающее, что «Протокол содержит недопустимый тег (ноль)».Я вполне уверен, что он не содержит недопустимый тег, так как сообщение работает при отправке его методом writedata.

Любая помощь по этому вопросу будет принята с благодарностью!

Ура!

Dan

(РЕДАКТИРОВАТЬ: я должен упомянуть, я использую метасинтаксический код gpb; и реализацию cocoaasyncsocket)

Ответы [ 2 ]

0 голосов
/ 11 июня 2010

Наконец мне удалось это решить !! Стыдно, как просто, когда я перестал заботиться о том, как это делать с GPB. Код C ++, который я использовал:

    NSData *data = [wrapper data]; 
    int s = [wrapper serializedSize]; 
    NSData *size = [NSData dataWithBytes:&s length:1]; 
    [sock writeData:size withTimeout:-1 tag:1]; 
    [sock writeData:data withTimeout:-1 tag:1]; 

и затем на стороне Java я просто сохранил

    RequestWrapper.parseDelimitedFrom(socket.getInputStream())

линия, и это работает удовольствие! Все, что я в итоге делаю, это отправляю размер данных до того, как сами данные, а метод GPB на стороне Java решает остальное!

Одной из основных проблем, с которыми я столкнулся, было преобразование размера данных для отправки из int в NSData и правильная их передача по сети. То, как мне посоветовали сделать это, было NSData * size = [NSData dataWithBytes: & s length: sizeof (s)];

Однако всякий раз, когда я отправлял это как данные, казалось, что он отправляет первый байт вместе с 3 «0» байтами. Это вызвало хаос с GPB, потому что если он получает 0 байт в любой момент, он генерирует исключение, думая, что код поврежден (мое предположение). Видя, что я никогда не смотрел на реальные байты, встречающиеся и анализирующие их, пока не попытался сделать это по-другому сегодня, я немного растерялся, поскольку мог бы понять, что это было проблемой некоторое время назад. Немного поэкспериментировав с ним, я понял, что проблема в методе sizeof, поэтому я удалил его. В настоящее время я просто поставил «1» вместо фактического размера, который кажется, возвращает только 1 байт при отправке файла данных по сети; хотя я не уверен, что это будет «идеальное» решение (хотя размер сообщения в любом случае должен быть только в 1 байте) - если кто-нибудь мог бы посоветовать мне, почему этот sizeof () вызывает проблему, это было бы желательно :)

Очки действительно должны поступить Люку Штеффену, который помог мне с этим в группе Google по cocoaasyncsocket, несмотря на мой идиотизм - так что еще раз, спасибо Люк!

0 голосов
/ 08 июня 2010

Может быть, вам нужно очистить выходной сокет на стороне iPhone, возможно, что данные находятся в буфере ОС / библиотеки и не записываются, пока соединение не будет закрыто (что вызывает неявное промывать).

EDIT

Похоже, что API не поддерживает сброс (я думаю, что сброс не очень асинхронный ), но вы можете подписаться на событие didWriteDataWithTag: из заголовков

/**
 * Called when a socket has completed writing the requested data. Not called if there is an error.
**/
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;

Я бы подписался на это событие, а затем в вызове обработчика события

[self updateLabel:@"Data sent, disconnecting"];
[socket disconnect];

таким образом, вы показываете метку Отправленные только тогда, когда она действительно отправлена.

(в интересах полного раскрытия я понятия не имею, как программировать в target-c :) удачи)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...