2009-05-20 25 views
7

Tôi kết nối không đồng bộ với máy chủ sau mỗi 5 giây. URL giống nhau, nhưng POST-body được thay đổi mỗi lần. Bây giờ tôi tạo NSURL, NSURLRequest và NSURLConnection từ đầu mỗi lần.NSURLConnection được chạy nhiều lần

Tôi nghĩ sẽ hiệu quả hơn khi đặt kết nối một lần và chỉ cần sử dụng kết nối đó một lần nữa. Tôi là một newbie và không chắc chắn nếu có thể. Không có NSURLConnection có thể thay đổi, nhưng có thể cần phải tạo NSURLConnection như:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: url]; 
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 

và thay đổi NSMutableURLYêu cầu POST để gửi yêu cầu khác đến máy chủ. Cách nào là đúng?

+0

nếu (! Kết nối) kết nối = [[NSURLKết nối kết nối] initWithRequest: yêu cầu ủy quyền: tự bắt đầuImmediately: NO]; [kết nối bắt đầu]; Cái này không hoạt động, nó cung cấp “EXC_BAD_ACCESS”. Tôi đã tìm kiếm các diễn đàn cho điều đó và không có câu trả lời. Có vẻ như 'bắt đầu' là cần thiết để sử dụng một cách khác. – slatvick

+0

Đó là một sự kỳ quặc của phương pháp khởi tạo này mà bạn phải lên lịch kết nối trên một runloop trước khi bắt đầu nó. –

Trả lời

9

Tôi cho rằng những gì bạn quan tâm là chi phí tạo kết nối HTTP. NSURLConnection đủ thông minh để xử lý việc này cho bạn bằng cách sử dụng HTTP/1.1 và sử dụng lại các kết nối hiện có. Nó không sử dụng pipelining thời gian qua tôi đã kiểm tra, nhưng cho mục đích của bạn, kết nối tái sử dụng nên là đủ. Tôi khuyến khích bạn đặt một sniffer mạng về điều này và chắc chắn rằng nó làm việc như bạn muốn họ.

Chi phí tự tạo các đối tượng là không đáng kể theo thứ tự của một lần cho mỗi 5s và bạn không nên cố gắng tối ưu hóa (mặc dù tất nhiên bạn nên sử dụng lại NSURL). Đó là việc mở một kết nối đến máy chủ đắt tiền, đặc biệt là trên iPhone.

Nếu bạn thấy bạn thực sự cần pipelining, bạn không may sẽ phải cuộn của riêng bạn. Tôi đã nghe nói rằng CFHTTPStream có thể làm điều đó, nhưng tôi không thấy nhiều bằng chứng về điều đó. CocoaAsyncSocket là đặt cược tốt nhất của bạn để truy cập cấp thấp vào các ổ cắm mà không cần phải viết mã mức thấp.

Vì độ trễ trên mạng di động có thể rất tệ, có thể kết nối của bạn sẽ mất nhiều hơn 5s để hoàn thành. Hãy chắc chắn rằng một kết nối được thực hiện trước khi bắt đầu tiếp theo, hoặc bạn sẽ bắt đầu thực hiện ngày càng nhiều kết nối mở.

+0

Cảm ơn bạn. Theo tôi hiểu NSURL sẽ mở một kết nối, đúng không? nếu vậy tôi không cần tối ưu hóa nhiều hơn nữa, tôi chỉ cần không mở kết nối mỗi 5 giây, điều này khá tốn kém, như bạn cũng hiểu. – slatvick

+2

Bản thân NSURL không mở kết nối. Nó chỉ phân tích chuỗi. NSURLConnection mở kết nối và nó xử lý việc tái sử dụng kết nối HTTP/1.1 cho bạn. –

+0

Tôi cần giữ kết nối còn sống và thay đổi NSMutableURLRequest POST-data gửi các POST khác nhau thông qua nó. Có thể không? Làm sao? – slatvick

0

tạo ra một phương thức trả về một yêu cầu và làm

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:[self requestMethod] delegate:self]; 

?

+0

[[NSURLConnection alloc] init ...]; nó tạo một kết nối mới mỗi lần, nhưng tôi muốn sử dụng một kết nối cho а dài chỉ thay đổi dữ liệu POST của yêu cầu theo: [yêu cầu setHTTPBody: newRequestData]; – slatvick

6

Chỉ cần làm rõ mọi thứ, NSURLConnection sẽ sử dụng lại các ổ cắm hiện có, nhưng chỉ trong một khung thời gian tương đối nhỏ (12 giây). Nếu bạn gửi một yêu cầu, lấy lại phản hồi và gửi yêu cầu tiếp theo trong vòng 12 giây mà yêu cầu thứ 2 sẽ xuất hiện trên cùng một ổ cắm. Nếu không, ổ cắm sẽ được đóng bởi khách hàng. Một lỗi đã được đệ trình với Apple để tăng bộ đếm thời gian này hoặc để làm cho nó có thể cấu hình được.

3

@Rob Napier @Eric Nelson Như bạn đã đề cập: "NSURLConnection đủ thông minh để xử lý việc này cho bạn bằng cách sử dụng HTTP/1.1 và sử dụng lại các kết nối hiện có". Tuy nhiên, tôi không thể tìm thấy mô tả như vậy trong bất kỳ tài liệu nào của Apple về điều đó.

Để thực hiện điều rõ ràng, tôi viết một số mã để kiểm tra nó:

- (IBAction)onClickSend:(id)sender { 
    [self sendOneRequest]; 
} 

-(void)sendOneRequest { 

    NSURL *url = [NSURL URLWithString:@"http://192.168.1.100:1234"]; 
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 
    [request setHTTPMethod:@"POST"]; 
    [request addValue:[Base64 encodeFromString:kValueVersion] forHTTPHeaderField:kKeyVersion]; 
    [request addValue:[Base64 encodeFromString:kValueDataTypeCmd] forHTTPHeaderField:kKeyDataType]; 
    [request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyCmdName]; 
    [request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyDeviceName]; 
    [request addValue:[Base64 encodeFromString:@"xxdafadfadfa"] forHTTPHeaderField:kKeyDTLCookies]; 
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
    [connection start]; 
} 

Và sau đó, tôi bắt đầu Wireshark để bắt gói trên máy chủ (192.168.1.xxx), sử dụng "(tcp.flags .syn == 1) || (tcp.flags == 0x0010 & & tcp.seq == 1 & & tcp.ack == 1) "để lọc tcp lắc tay 3 chiều. Thật không may, tôi có thể thấy rung tay 3 chiều cho mỗi lần gọi "sendOneRequest". Có nghĩa là, NSURLConnection dường như không tái sử dụng các kết nối hiện có. Một số có thể chỉ ra những gì sai trong mã của tôi và làm thế nào để gửi nhiều yêu cầu thông qua một kết nối socket bởi NSURLConnection?

Tôi cũng đã cố gắng cách đồng bộ để gửi yêu cầu:

-(void)sendOneRequest { 
    NSURL *url = [NSURL URLWithString:@"http://192.168.1.100:1234"]; 
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 
    [request setHTTPMethod:@"POST"]; 
    [request addValue:[Base64 encodeFromString:kValueVersion] forHTTPHeaderField:kKeyVersion]; 
    [request addValue:[Base64 encodeFromString:kValueDataTypeCmd] forHTTPHeaderField:kKeyDataType]; 
    [request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyCmdName]; 
    [request addValue:[Base64 encodeFromString:@"Test"] forHTTPHeaderField:kKeyDeviceName]; 
    [request addValue:[Base64 encodeFromString:@"xxdafadfadfa"] forHTTPHeaderField:kKeyDTLCookies]; 

    [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 

    sleep(1); 

    [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 

    sleep(1); 

    [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 

} 

Và kết quả là như nhau.

======= CẬP NHẬT ============================

Cuối cùng, tôi đã tìm thấy lý do tại sao bài kiểm tra của tôi khác với Rob và Eric nói. Tóm lại, Rob và Eric là chính xác. Và NSURLConnection sử dụng "keep-alive" làm mặc định cho việc sử dụng HTTP/1.1 và tái sử dụng kết nối socket hiện có, nhưng chỉ cho một khung thời gian tương đối nhỏ.

Tuy nhiên, NSURLConnection có một số vấn đề về "mã chuyển mã chunked" (nghĩa là không có độ dài nội dung). Trong thử nghiệm của tôi, phía máy chủ gửi phản hồi mà không có dữ liệu về độ dài và nội dung đáp ứng, và phản hồi chunked của nó và NSURLConnection sẽ đóng kết nối, do đó rung tay 3 chiều xảy ra cho mỗi bài viết http.

Tôi đã thay đổi mã máy chủ của mình, đặt độ dài phản hồi là 0 và hành vi là chính xác.

Các vấn đề liên quan