Mạng trao đổi tin nhắn máy khách-máy chủ và đồng bộ hóa trợ giúp


10

Tôi đang làm một trò chơi vật lý có nhịp độ nhanh đó là khúc côn cầu trên bàn. Với hai vồ và một puck. Trò chơi chạy trên iphone / ipad và tôi đang thực hiện phần nhiều người chơi thông qua GameCenter.

Đây là cách hệ thống mạng hoạt động. Máy khách sẽ đánh dấu sao trận đấu, sẽ được giải quyết dưới dạng máy chủ và người chấp nhận yêu cầu đối sánh là máy khách.

'Máy chủ' có vật lý đang chạy và phản hồi ngay lập tức và máy khách cũng có vật lý của chúng chạy để nó trông mượt mà giữa các trao đổi tin nhắn. Những gì tôi làm với tư cách là máy chủ, là tôi gửi cho khách hàng vận tốc puck của tôi và vị trí của tôi và khách hàng điều chỉnh vận tốc / vị trí puck của anh ta liên quan đến máy chủ để giữ cho nó được đồng bộ hóa. Mặt khác, vật lý không đồng bộ hóa và nó vặn nó lên.

Khi độ trễ mạng tốt, dưới 100ms kết quả khá tốt, tôi có một trò chơi mượt mà ở phía khách hàng và hành vi kỳ lạ là tối thiểu. Vấn đề xảy ra khi độ trễ khoảng 150 đến 200ms. Trong trường hợp đó, xảy ra việc khách hàng của tôi đã ném một cạnh và đảo ngược hướng nhưng nó nhận được một thông báo chậm trễ từ máy chủ và nó quay lại một chút gây ra cảm giác kỳ lạ cho hành vi bóng.

Tôi đã đọc một vài điều về nó:

Ví dụ về mạng lưới

Nhấp vào ví dụ đồng bộ hóa

Wikipedia trên Đồng bộ hóa đồng hồ

Vì vậy, làm thế nào tôi có thể giải quyết điều này? Theo như tôi đã đọc tùy chọn tốt nhất mà tôi có là thực hiện đồng bộ hóa đồng hồ trên máy chủ / máy khách với dấu thời gian để khi tôi nhận được thông báo trễ liên quan đến đồng hồ của mình, tôi chỉ cần bỏ qua và để cho máy khách mô phỏng việc làm. Các bạn có đồng ý với điều đó không? Và vì tôi đang gửi dữ liệu không đáng tin cậy (UDP) nên tôi có thể nhận được tin nhắn hoặc tin nhắn bị trì hoãn.

Nếu đó là cách tiếp cận tốt nhất, làm thế nào để tôi thực hiện đồng bộ hóa đồng hồ. Tôi đã đọc các bước về cách làm nhưng tôi không hiểu lắm.

Nó nói rằng:

  1. Khách hàng đóng dấu giờ địa phương hiện tại trên gói "yêu cầu thời gian" và gửi đến máy chủ.
  2. Khi nhận được bởi máy chủ, máy chủ đóng dấu thời gian máy chủ và trả lại
  3. Khi khách hàng nhận được, khách hàng sẽ trừ thời gian hiện tại khỏi thời gian gửi và chia cho hai để tính độ trễ. Nó trừ thời gian hiện tại từ thời gian máy chủ để xác định delta thời gian của máy khách-máy chủ và thêm vào độ trễ một nửa để có được đồng hồ chính xác. (Cho đến nay algothim này rất giống với SNTP)
  4. Khách hàng lặp lại các bước từ 1 đến 3 năm lần trở lên, tạm dừng vài giây mỗi lần. Lưu lượng khác có thể được cho phép trong thời gian tạm thời, nhưng nên được giảm thiểu để có kết quả tốt nhất Kết quả của các biên nhận gói được tích lũy và sắp xếp theo thứ tự độ trễ thấp nhất đến độ trễ cao nhất. Độ trễ trung bình được xác định bằng cách chọn mẫu điểm giữa từ danh sách được sắp xếp này.
  5. Tất cả các mẫu trên khoảng 1 độ lệch chuẩn so với trung vị đều bị loại bỏ và các mẫu còn lại được lấy trung bình bằng trung bình số học.

Theo ví dụ này tôi sẽ có cái này:

Hãy giả vờ trò chơi đã tải và thời gian khách hàng của tôi là 0, vì vậy tôi gửi cho máy chủ rằng thời gian của tôi là 0.

Các tin nhắn mất 150ms để đến máy chủ nhưng đồng hồ của máy chủ đã bắt đầu và đi trước khách hàng 1 giây. Khi máy chủ nhận được thông báo, thời gian sẽ là: 1.15 và gửi thời gian đó cho khách hàng, chúng ta có tốt không? Hãy giả vờ độ trễ của chúng tôi là không đổi ở 150ms.

Bây giờ khách hàng nhận được thời gian 1,15 và trừ thời gian hiện tại từ thời gian gửi và chia cho hai để tính độ trễ. Giá trị là: 0,3 - 0 = 0,3 / 2 -> 150ms.

Nó trừ thời gian hiện tại khỏi thời gian máy chủ để xác định đồng bằng thời gian của máy khách-máy chủ và thêm thời gian trễ một nửa để có được đồng hồ chính xác:
Thời gian máy khách: 0,3 Thời gian máy chủ 1.15
0,3 - 1,15 = 0,85 + độ trễ (.15) = 1

Làm thế nào là đồng bộ? Tôi đang thiếu gì

Đây là lần đầu tiên tôi trải nghiệm nhiều người chơi và trải nghiệm mạng, vì vậy tôi hơi bối rối.

Cảm ơn bạn.


Câu hỏi hay. Bạn có thể sửa: 0,3 - 1,15 thành 1,15 - 0,3?
Ciara

Câu trả lời:


12

Thuật toán được đăng là chính xác, nhưng trong ví dụ của bạn, bạn đang quên mất thời gian để gói máy chủ đến máy khách, vì vậy:

Server time: 1
Client time: 0
Client sends 0 to server

... 150ms to get to server  (ping is 300! not 150ms in this case. Ping is round-trip)

Server time: 1.15
Client time: 0.15
Server receives packet and sends client 1.15

... 150ms to get back to client

Server time: 1.30
Client time: 0.30
Client receives 1.15 from server

Bây giờ bạn có thể thấy, nếu máy khách thay đổi đồng hồ thành 1,15, nó sẽ chậm hơn 0,15 so với máy chủ, đây là lý do tại sao bạn phải điều chỉnh cho Ping (còn gọi là Thời gian khứ hồi [RTT]). Dưới đây là tính toán thời gian delta đầy đủ được thực hiện qua nhiều bước:

Server Time - Current Time + Ping / 2
= Server Time - Current Time + (Current Time - First Packet Time) / 2
= 1.15 (Perceived, not actual!) - 0.30 + (0.30 - 0.00) / 2
= 1.00

Điều này cho chúng ta thời gian delta chính xác là 1,00 giây


Tôi nhận được nó, vì vậy đồng hồ khách của tôi là 1,00 và máy chủ là 1,30 Sau khi tôi nhận được tin nhắn từ máy chủ, tôi có phải thêm ping để kiểm tra xem có phải là tin nhắn trễ hay không? Một điều nữa, nếu độ trễ thay đổi, tôi có phải tiếp tục làm những việc đó không?
gmemario

Thời gian delta của 1,00 sẽ được thêm vào đồng hồ hiện tại để làm cho thời gian của khách hàng bằng với thời gian của máy chủ. Độ trễ luôn thay đổi, mỗi gói sẽ có RTT hơi khác nhau. Trong một khung thời gian ngắn như trong trò chơi, tôi chỉ cần thực hiện đồng bộ hóa thời gian này một lần duy nhất, khách hàng sẽ có một dự đoán khá chính xác về thời gian của máy chủ và cả hai đồng hồ sẽ di chuyển về phía trước với cùng tốc độ. Chỉ có ngoại lệ là nếu bạn nhận được một gói có vẻ là từ tương lai. Trong trường hợp đó, có 2 giải pháp: 1) Thực hiện đồng bộ hóa thời gian mới. 2) Nâng cao đồng hồ của bạn để phù hợp với đồng hồ trong tương lai
John McDonald

Ok, chúng ta hãy xem xét tình huống này để đảm bảo rằng tôi đã nhận được: Thời gian máy chủ: 1 giây Thời gian của khách hàng: 0 giây 150ms để đến máy chủ Thời gian máy chủ: 1.15s Thời gian của khách hàng: 0.15s Máy chủ gửi máy khách 1.15 giây 200ms để đến máy khách Vì vậy, ping của tôi bây giờ là 350ms. Đúng không? Thời gian máy chủ: 1.35 Thời gian của khách hàng: 0.35 Thực hiện các calcs: 1.15 - .35 + (0.35 - 0.00) / 2 Bây giờ deltaTime của tôi = 0,975 Nếu tôi thêm thời gian delta 0,975 vào .35 tôi nhận được: 1.325. Điều đó có đúng không?
gmemario

@Gilson, Đúng vậy. Nếu độ trễ cho hai gói là khác nhau (gần như được bảo đảm), phép tính thời gian delta của máy khách sẽ không hoàn hảo. Không có cách nào để khách hàng trở nên hoàn hảo. Trong thuật toán bạn mô tả trong câu hỏi, thời gian delta được tính một số lần và có một phương pháp để chọn và lấy trung bình các kết quả này. Nhiều phương thức đồng bộ hóa thời gian sẽ làm một cái gì đó như thế này, nhưng chúng thường dành cho các máy chủ quan trọng và hoạt động lâu dài như cho các sàn giao dịch chứng khoán. Đối với độ chính xác thời gian bạn yêu cầu cho một trò chơi ngắn, tôi nghĩ rằng đó sẽ là quá mức cần thiết.
John McDonald

@Gilson, Miễn là khách hàng có ước tính hợp lý về thời gian của máy chủ và cả hai đồng hồ di chuyển về phía trước với tốc độ gần như nhau, bạn không nên nhận thấy bất kỳ vấn đề nào. Khi khách hàng hoặc máy chủ gửi một hành động sang phía bên kia, họ sẽ gửi giờ địa phương của họ. Về phía nhận, thông điệp phải luôn ở trong quá khứ và sẽ cần được hiểu là một sự kiện trong quá khứ. Điều này có nghĩa là bạn cần tất cả thông tin trong gói, như vị trí, vận tốc (cường độ + hướng) và thời gian. Sau đó, bạn có thể đặt puck ở đó và sau đó, và di chuyển puck từ quá khứ đến hiện tại. Tôi đang trò chuyện btw
John McDonald
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.