Câu hỏi Trung tâm trò chơi GKMatch GKSendDataReliable packet lost


Tôi đã sử dụng GKMatch trong một thời gian khá thành công trong một ứng dụng. Tôi đã theo đuổi và phát hành với các trò chơi đôi khi dừng lại và đã theo dõi nó xuống các gói tin được gửi nhưng không nhận được. Điều này chỉ thỉnh thoảng xảy ra nhưng tôi dường như không thể theo dõi lý do tại sao nó xảy ra.

Tất cả thư được gửi bằng GKSendDataReliable.

Việc ghi nhật ký cho thấy rằng gói đang được gửi từ một thiết bị thành công, nhưng nó không bao giờ được nhận tại thiết bị đích.

//Code sample of sending method....
//self.model.match is a GKMatch instance    
-(BOOL) sendDataToAllPlayers:(NSData *)data error:(NSError **)error {
        [self.model.debugger addToLog:@"GKManager - sending data"];
        return [self.model.match sendDataToAllPlayers:data withDataMode:GKSendDataReliable error:error];
    }

...

//Code sample of receiving method....
// The match received data sent from the player.
-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
    [self.model.debugger addToLog:@"GKManager - received data"];
    [super didReceiveData:data fromPlayer:playerID];
}

Những gì tôi thấy xảy ra là định kỳ (có thể 1 trong 100 tin nhắn) được gửi mà không có lỗi từ phương thức 'sendDataToAllPlayers', nhưng thiết bị nhận không bao giờ chạm vào phương thức 'didReceiveData'. Sự hiểu biết của tôi là sử dụng GKSendDataReliable sẽ gửi tin nhắn và sau đó sẽ không gửi tin nhắn khác cho đến khi nhận được xác nhận. Tin nhắn không được nhận nhưng tin nhắn mới được gửi từ cùng một thiết bị.

Phương thức gửi trả về 'CÓ' và lỗi là không, nhưng didReceiveData không bao giờ được nhấn ...!

Có ai đã từng nhìn thấy điều này? Có ai có bất kỳ ý tưởng này có thể là gì? Tôi không biết những gì khác tôi có thể làm để gỡ lỗi này.


11
2018-06-07 15:35


gốc


Người dùng của tôi cũng phàn nàn rằng một số dữ liệu có thể vô tình bị mất trong trò chơi. Nhưng tôi vẫn không thể tự mình tái tạo lỗi này. Bạn có một dự án ví dụ mà lỗi này có thể tái sản xuất liên tục không? Nếu có, bạn có thể vui lòng chia sẻ nó (có thể là trên github)? Cảm ơn. - Yan
Dự án của tôi là rất lớn (ứng dụng hoạt động trong cửa hàng hiện tại) nhưng tôi sẽ cố gắng và đặt cùng một phiên bản nhỏ hơn của nó để xem liệu nó có thể lặp lại liên tục hay không. - Jonathan Hebert
Tôi đang gặp vấn đề tương tự, đặc biệt khi kết nối internet trên một trong các thiết bị yếu. Có đúng là GKSendDataReliable ngừng gửi tin nhắn cho đến khi nhận được xác nhận không? - jyek
Bạn đã gửi báo cáo lỗi cho điều này chưa? Điều này có vẻ như chức năng bị hỏng cơ bản sẽ ảnh hưởng đến bất kỳ nhà phát triển nào sử dụng các kết quả phù hợp trong thời gian thực. - Shaun Budhram
Tôi cũng đã xác nhận điều này. Thực sự rất ngạc nhiên từ Apple (chưa kể đến thất vọng). Toàn bộ các điểm của chế độ đáng tin cậy là kết nối nên đệm và trì hoãn cho đến khi nó có thể gửi, không chỉ thả tin nhắn. - theLastNightTrain


Các câu trả lời:


Tôi xác nhận lỗi. Tôi đã thực hiện một dự án ví dụ về việc tái tạo vấn đề một cách nhất quán: https://github.com/rabovik/GKMatchPacketLostExample. Tôi đã thử nghiệm nó trên một kết nối internet yếu (iPad 3 với Wi-Fi và iPhone 4S với EDGE; cả trên iOS 6.1.3), và một số gói tin thường xuyên bị mất mà không có bất kỳ lỗi nào từ Game Center API. Hơn nữa, đôi khi thiết bị dừng nhận bất kỳ dữ liệu nào, trong khi thiết bị khác vẫn gửi và nhận tin nhắn thành công.

Vì vậy, nếu chúng tôi chắc chắn lỗi tồn tại, cách giải quyết duy nhất có thể là thêm một lớp vận chuyển bổ sung để phân phối thực sự đáng tin cậy.

Tôi đã viết một lib đơn giản cho mục đích này: https://github.com/rabovik/RoUTP. Nó lưu tất cả các tin nhắn đã gửi cho đến khi nhận được thông báo cho mỗi nhận được, gửi lại bị mất và bộ đệm nhận được tin nhắn trong trường hợp chuỗi bị hỏng. Trong thử nghiệm của tôi kết hợp "RoUTP + GKMatchSendDataUnreliable" hoạt động ngay cả beter hơn "RoUTP + GKMatchSendDataReliable" (và tất nhiên tốt hơn so với GKMatchSendDataReliable tinh khiết mà không thực sự đáng tin cậy).


8
2017-07-06 13:13



RoUTP dường như bị hỏng ngay bây giờ với iOS 9. Nếu tôi gửi dữ liệu bằng cách sử dụng nó không phải tất cả các thiết bị sẽ nhận được dữ liệu. Không quan trọng nếu tôi sử dụng phương tiện giao thông đáng tin cậy hoặc không đáng tin cậy. Nếu tôi vô hiệu hóa tất cả mọi thứ RoUTP hoạt động tốt. - Robert Wasmann


[Chỉnh sửa: RoUTP dường như không hoạt động đúng cách trong iOS9]

Tôi đã làm một số thử nghiệm ngày hôm qua ở rìa phạm vi wifi của tôi, nơi mất gói tin đã xảy ra. Điều xảy ra là khi các gói bị mất bằng cách sử dụng GKMatchSendDataReliable, trình phát bị ngắt kết nối đột ngột từ phiên GKMatch. match: player: didChangeState được gọi với GKPlayerStateDisconnected và ID của người chơi bị xóa khỏi từ điển playerID. Điều này xảy ra với chỉ mất gói tin nhỏ. Tôi vẫn có thể duyệt internet từ kết nối này chẳng hạn.

Bây giờ, nếu tôi chuyển sang gửi gói không chính xác, thì khớp: player: didChangeState không bao giờ kích hoạt và trận đấu tiếp diễn mà không gặp sự cố (ngoại trừ việc mất gói thỉnh thoảng có thể quan trọng). Nó sẽ chỉ ngắt kết nối nếu mất gói tin trở nên đáng kể. Bây giờ đây là nơi thư viện RoUTP của Yan rất tiện dụng, vì chúng ta có thể theo dõi và thử lại những thông điệp quan trọng này mà không để người chơi bị ngắt kết nối khi họ gặp phải mất gói dữ liệu nhỏ.

Ngoài ra, việc gửi dữ liệu bằng GKMatchSendDataReliable sẽ chỉ trả về CÓ nếu tin nhắn đã được xếp thành công để phân phối. Nó không cho bạn biết tin nhắn có được gửi thành công hay không. Làm thế nào có thể nó? Nó trở lại ngay lập tức.


1
2017-11-10 15:16



Hey tôi đã làm việc trên một trò chơi rts khá phức tạp và tôi đã nhận thấy chính xác vấn đề bạn đang mô tả. Bạn có đề nghị tôi thử thư viện RoUTP không? - Epic Byte
Nó chắc chắn hoạt động, nhưng nó rất cơ bản. Ví dụ, tất cả các gói tin phải được gửi qua RoUTP khi bạn bắt đầu sử dụng nó. Và nó sẽ tiếp tục cố gắng để cung cấp các gói tin mãi mãi. Điều này có thể gây ra một loạt các gói bị trì hoãn đi qua tất cả cùng một lúc. Tôi có thể xem xét việc đi máy chủ khách hàng đầy đủ thay vì ngang hàng và bỏ qua RoUTP. Nếu khách hàng bị mất gói và bị ngắt kết nối thì đó có thể là một kết quả mong muốn để giữ cho trò chơi bình thường đối với các khách hàng khác, thay vì có một người chơi xuất hiện xung quanh cảnh giết người chơi khác trước khi bất kỳ ai có thể phản ứng vì các gói tăng vọt. - Robert Wasmann
Nó cũng không nói ai gửi gói tin nào vì thông tin đó bị loại bỏ. Vì vậy, bạn phải mã hóa playerID vào thư bằng cách sử dụng mảng char. Tất cả người chơi nhận được tất cả các tin nhắn, vì vậy nếu bạn đi máy chủ khách hàng thì nó không lý tưởng. Tức là, bạn không thể gửi tin nhắn cho người chơi cụ thể. Chỉ cho tất cả người chơi và sau đó có người chơi bỏ qua các tin nhắn không dành cho họ. - Robert Wasmann
Xin cảm ơn vì đã trả lời. Vì vậy, ban đầu tôi đã gửi gói tin đáng tin cậy nhưng do cách mà Trung tâm trò chơi xử lý ngắt kết nối với các gói tin đáng tin cậy, tôi cần thử một thứ khác vì ngay cả thời gian chờ nhỏ nhất cũng sẽ ngắt kết nối người dùng. Vì vậy, những gì tôi đã kết thúc làm là viết lớp của riêng tôi qua tin nhắn gửi không đáng tin cậy và quản lý hàng đợi đáng tin cậy bản thân mình. Điều này cho phép tôi ưu tiên một số thông điệp nhất định và tự thả các gói nếu chúng không còn cần thiết nữa (I.e. Nếu mất quá nhiều thời gian). Tôi đã thành công cho đến nay với cách tiếp cận này. Và không có ngắt kết nối đang xảy ra. - Epic Byte
Trong nhiều năm, tôi đã trải qua cả việc mất gói tin "đáng tin cậy" và ngắt kết nối -didChangeState tự phát. Tôi không bao giờ nghĩ rằng mất gói tin đáng tin cậy sẽ gây ra một ngắt kết nối, vì vậy tôi đã làm một bài kiểm tra nhanh chóng bằng cách thay đổi tất cả các dữ liệu của tôi không đáng tin cậy. Không thay đổi. Tôi vẫn nhận được các ngắt kết nối -didChangeState trên một trò chơi 3 hoặc 4 người chơi. Dường như không xảy ra trong 2 game thủ. - BGreenstone