2011-07-22 23 views
5

TCP soket tabanlı sunucumda, paketlerin paket içindeki bayt sayısını ve ardından bu bayt sayısını belirten bir üstbilgiden oluştuğu bir paket gönderirim. Erlang'ı tanıyanlar için, sadece {packet, 4} seçeneğini ayarlıyorum.CocoaAsyncBir soketten veri okuma ve okuma verileri

[asyncSocket readDataToLength:4 withTimeout:-1 tag:HEADER_TAG]; 
çalışıyor

ve aşağıdaki temsilci yöntemi geri arama çağrılır:

iOS tarafında, ben bu mesajı için akımının büyüklüğünü anlamaya istiyorum varsayarak aşağıdaki gibi görünür koduna sahip

onSocket:didReadData:withTag: 
sonraki mantıksal aşama akımının boyutunu anlamaya olduğunu anlamaya ve birlikte bunu:

UInt32 readLength; 
    [data getBytes:&readLength length:4]; 
    readLength = ntohl(readLength); 

sunucu tarafında 12 baytlık bir dizi kod sabit sonra readLength i yapar Gerçekten de müşteri üzerinde 12 okudu, bu yüzden her şey yolunda. Ben aşağıda devam:

[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG]; 

Bu noktada geri arama onSocket:didReadData:withTag: artık çağrılır bile. ,

- (NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length 

böylece toplamda, sunucu gönderen 16 bayt 4 byte başlık ve 12: Bunun yerine bu temsilci yöntemi çağrılan, düzgün okuma idare etmedi çünkü muhtemelen gerçekleştiğini okuma üzerine zaman aşımı Bayt ikili akışı.

Hata, CocoaAsyncSocket'ı nasıl kullandığım konusunda eminim. Boyutunu bulduktan sonra akıntının geri kalanını okumak için doğru yol nedir?

** GÜNCELLEME **

Ben müvekkilimi değişti ve şimdi çalışıyor görünüyor. Sorun şu ki, yeni çözümle readDataToLength noktasını anlamıyorum. İşte benim ilk okuma değişti ne: Benim geri arama Şimdi

[socket readDataWithTimeout:-1 tag:HEADER_TAG]; 

, sadece aşağıdakileri yapın:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { 
    if (tag == HEADER_TAG) { 
     UInt32 readLength; 
     [data getBytes:&readLength length:4]; 
     readLength = ntohl(readLength); 
     int offset = 4; 
     NSRange range = NSMakeRange(offset, readLength); 
     char buffer[readLength]; 
     [data getBytes:&buffer range:range]; 
     NSLog(@"buffer %s", buffer); 
     //[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG]; 
    } else if (tag == MESSAGE_TAG) { 
     //[sock readDataToLength:4 withTimeout:1 tag:HEADER_TAG]; 
    } 

} 

Yani her şey biri, atomik yük olarak geliyor

. Belki de bu, Erlang {packet, 4} 'ün işleyişinden kaynaklanıyor. Umarım öyledir. Aksi takdirde, readDataToLength'un noktası nedir? Bir iletinin uzunluğunu istemciden önceden bilmenin bir yolu yok, bu nedenle bu yöntemi kullanmak için iyi bir kullanım durumu nedir?

cevap

1

Erlang tarafından nasıl gönderdiğine bağlı olarak, sanırım. {packet, 4} seçeneği, her veri paketine öntanımlı 4 baytlık bir uzunluk gönderir. Erlang'daki her gönderim işlemi, bir paketin uzunluğu önceden eklenmiş olarak gönderilir (4 uzunluğu için maksimum boyut, örneğin 2 Gb'dir). Erlang belgelerinin ilgili kısmı setting the socket options using inet:setopts/2 içindir.

Veriler, şimdiye kadar soketten okunan toplam birikmiş veri olduğunu tahmin ediyorum. Bu veri bütün paketinizi içeriyorsa, sorun değil. Ancak eğer değilse, kalan verilerle readDataToLength kullanarak soketten bloke edilmiş bir okuma yapmaya devam etmek isteyebilirsiniz.