UDP không chặn hoặc một luồng riêng biệt để nhận?


10

Tôi đang tạo một trò chơi nhiều người chơi (dành cho dưới 64 người chơi). Tôi đã quyết định có một luồng riêng cho vòng lặp mạng, nhưng tôi tự hỏi liệu có tốt hơn không khi tạo một luồng bổ sung để nhận UDP hoặc đặt ổ cắm nhận không chặn (không có luồng phụ).

Hoặc tốt hơn là sử dụng một phương pháp khác như Ổ cắm không đồng bộ? Phương pháp tốt hơn luôn được chào đón!

Câu trả lời:


6

Được rồi, trước hết, nếu bạn có một cái gì đó và nó đang hoạt động, thường thì nên để nó như thế. Tại sao phải sửa những gì không bị hỏng?

Nhưng nếu bạn gặp sự cố và thực sự muốn viết lại mã mạng của mình, tôi nghĩ bạn có bốn lựa chọn chính:

  1. Mã chặn đa luồng (những gì bạn đang làm ngay bây giờ)
  2. Ổ cắm không chặn với thông báo kích hoạt cấp
  3. Ổ cắm không chặn với thông báo thay đổi sẵn sàng
  4. Ổ cắm không đồng bộ

Đã viết rất nhiều máy khách và máy chủ nhiều người chơi (từ ngang hàng đến nhiều người chơi), tôi muốn nghĩ rằng tùy chọn 2 dẫn đến độ phức tạp ít nhất, với hiệu suất khá tốt, cho cả phần máy chủ và máy khách của trò chơi. Gần một giây, tôi sẽ chọn tùy chọn 4, nhưng điều đó thường đòi hỏi bạn phải suy nghĩ lại về toàn bộ chương trình của mình và tôi chủ yếu thấy nó hữu ích cho các máy chủ chứ không phải máy khách.

Đặc biệt, tôi muốn khuyên bạn không nên chặn các socket trong môi trường đa luồng, vì làm như vậy thường dẫn đến khóa và các tính năng đồng bộ hóa khác không chỉ làm tăng đáng kể độ phức tạp của mã, mà còn có thể làm giảm hiệu suất của nó, vì một số luồng chờ khác.

Nhưng trên hết, hầu hết các triển khai ổ cắm (và hầu hết các triển khai I / O tại đó) đều không chặn ở mức thấp nhất. Các hoạt động chặn được cung cấp đơn giản để đơn giản hóa việc phát triển các chương trình tầm thường. Khi một ổ cắm bị chặn, CPU trong luồng đó hoàn toàn không hoạt động, vậy tại sao lại xây dựng một sự trừu tượng hóa không chặn đối với sự trừu tượng hóa chặn đối với một nhiệm vụ không chặn?

Lập trình ổ cắm không chặn là một chút khó khăn nếu bạn chưa thử nó, nhưng hóa ra nó khá đơn giản và nếu bạn đang thực hiện bỏ phiếu đầu vào, bạn đã có suy nghĩ để thực hiện các ổ cắm không chặn.

Điều đầu tiên bạn muốn làm là đặt ổ cắm thành không chặn. Bạn làm điều đó với fcntl().

Sau đó, trước khi bạn làm send(), recv(), sendto(), recvfrom(), accept()( connect()là một khác nhau bit) hoặc cuộc gọi khác mà có thể ngăn chặn các chủ đề, bạn gọi select()vào ổ cắm. select()cho bạn biết liệu một thao tác đọc hoặc ghi tiếp theo có thể được thực hiện trên ổ cắm mà không bị chặn hay không. Nếu đó là trường hợp, bạn có thể thực hiện thao tác bạn muốn một cách an toàn và ổ cắm sẽ không chặn.

Bao gồm điều này trong một trò chơi khá đơn giản. Nếu bạn đã có một vòng lặp trò chơi, ví dụ như thế này:

while game_is_running do
    poll_input()
    update_world()
    do_sounds()
    draw_world()
end

bạn có thể thay đổi nó thành như thế này:

while game_is_running do
    poll_input()
    read_network()
    update_world()
    do_sounds()
    write_network()
    draw_world()
end

Ở đâu

function read_network()
    while select(socket, READ) do
        game.net_input.enqueue(recv(socket))
    end
end

function write_network()
    while not game.net_output.empty and select(socket, WRITE) do
        send(socket, game.net_output.dequeue())
    end
end

Về tài nguyên, cuốn sách duy nhất tôi nghĩ mọi người phải có trong giá sách của mình, ngay cả khi đó là cuốn sách duy nhất họ có, là " Lập trình mạng Unix, Tập 1. " của cố Richard Stevens. Không thành vấn đề nếu bạn làm Windows hoặc lập trình ổ cắm ngôn ngữ hoặc hệ điều hành khác. Đừng nghĩ rằng bạn hiểu ổ cắm cho đến khi bạn đọc cuốn sách này.

Một tài nguyên khác mà bạn có thể tìm thấy tổng quan chung về các giải pháp khả dụng về mặt lập trình nhiều ổ cắm (chủ yếu liên quan đến lập trình máy chủ) là trang này .


Tôi mới khởi động công cụ trò chơi của mình, vì vậy việc viết lại không phải là vấn đề. Câu trả lời này thực sự hữu ích và cảm ơn bạn đã giới thiệu sách. Bạn có biết một cuốn sách cụ thể hơn về kết nối mạng trong các trò chơi không?
Yannick Lange

3
@YannickLange: Không, nhưng tôi không khuyên bạn nên tìm những cuốn sách dành riêng cho trò chơi, vì mạng không có nhiều thể loại, và cũng không có cuốn sách nào khác ngang tầm với cuốn sách của Stevens. Mặc dù vậy, việc sử dụng UDP là một giao thức hướng thông điệp là một ý tưởng tốt khi viết các chương trình hướng thông điệp (giống như hầu hết các trò chơi). Nhiều người có xu hướng kết thúc việc viết một bản tóm tắt thông điệp trên TCP, bản thân nó là một bản tóm tắt hướng luồng được xây dựng trên một giao thức hướng thông báo (IP).
Panda Pajama

-1

Bạn đã không viết ngôn ngữ lập trình nào bạn đang sử dụng, nhưng hầu hết các ngôn ngữ đều cung cấp khung ổ cắm không đồng bộ tốt, thường sử dụng các tính năng của hệ điều hành cơ bản.

Khi bạn viết triển khai luồng của riêng mình dựa trên việc chặn ổ cắm (hãy nhớ: khi bạn có nhiều máy khách, bạn cần một luồng cho mỗi ổ cắm), bạn sẽ chỉ phát minh lại khung ổ cắm không đồng bộ đã cung cấp.

Vì vậy, tôi khuyên bạn nên sử dụng ổ cắm không đồng bộ.


4
Tại sao anh ta cần một chủ đề cho mỗi ổ cắm? Đặc biệt với ổ cắm async? Nhiều máy chủ hạng nặng sử dụng mô hình "nhóm luồng" để xử lý dữ liệu ổ cắm, trong đó mỗi luồng dịch vụ N máy khách và chúng được sinh ra hoặc bị giết khi cần thiết. Chỉ cần nghĩ rằng câu trả lời này cần một sự cải tiến: D
Grimshaw

@Grimshaw Tôi nghĩ bạn đã hiểu nhầm câu trả lời của tôi. Tôi nghĩ rằng bây giờ tôi đã làm rõ rằng một mô hình đa luồng sẽ được yêu cầu khi sử dụng các ổ cắm chặn.
Philipp

@Philipp Tôi không nói ngôn ngữ lập trình nào tôi sử dụng bởi vì, tôi nghĩ rằng nó không thực sự phù hợp với câu hỏi (nhân tiện tôi sử dụng c ++). Tôi cảm ơn bạn đã khuyến nghị sử dụng ổ cắm không đồng bộ. Bạn có biết một cuốn sách / trang web được đề xuất để học các loại phương pháp này trong trò chơi (công cụ) không?
Yannick Lange

@Grimshaw: Và làm thế nào để mỗi Nkhách hàng dịch vụ luồng ? Nếu bạn đang chặn và bạn muốn đảm bảo mỗi ổ cắm được xử lý dữ liệu của nó bất kể trạng thái của các ổ cắm còn lại, bạn phải có một luồng trên mỗi ổ cắm. Điều đó, hoặc không sử dụng ổ cắm chặn.
Panda Pajama

Nhận xét của tôi là phiên bản đầu tiên của câu trả lời của bạn, trong khi đó, bạn đã chỉnh sửa và sửa nó, quên những gì tôi đã nói: D
Grimshaw
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.