2009-07-02 41 views
38

Tôi cần một ứng dụng gửi gói UDP tới một số máy chủ mạng và nhận được phản hồi. Máy chủ trả lời cùng một số cổng mà yêu cầu đến từ, vì vậy trước tiên tôi cần phải kết nối() ổ cắm của tôi với bất kỳ số cổng UDP nào.Cách liên kết với bất kỳ cổng nào có sẵn?

Mã hóa số cổng UDP là một ý tưởng tồi, vì nó có thể được sử dụng bởi bất kỳ ứng dụng nào khác đang chạy trên cùng một máy tính.

Có cách nào để liên kết ổ cắm UDP với bất kỳ cổng nào có sẵn không? IMO nó phải là một cách hiệu quả để nhanh chóng có được một cổng miễn phí #, được sử dụng bởi ví dụ: Hàm accept().

Nếu không, thì chiến lược nào tốt nhất để thử ràng buộc và kiểm tra trạng thái WSAEADDRINUSE/EADDRINUSE: thử các cổng tuần tự bắt đầu từ 1025 hoặc 1025 + rand() hoặc một số khác?

+1

accept() được sử dụng trong các ổ cắm dựa trên kết nối, chứ không được sử dụng trong các gói dữ liệu. – Beano

+1

có thể điều này sẽ giúp: http://serverfault.com/questions/447044 – yegor256

+0

Trong POSIX? Cũng yêu cầu dải 1024+: http://stackoverflow.com/questions/913501/how-to-let-kernel-choose-a-port-number-in-the-range-1024-5000-in-tcp-socket- pr –

Trả lời

34

Gọi sendto mà không gọi số bind trước, ổ cắm sẽ tự động bị ràng buộc (với một cổng miễn phí).

+5

Downvoting chỉ vì câu trả lời đúng phải là @ của Remy (sử dụng cổng 0 trong ràng buộc). – claf

+4

@claf ràng buộc ngầm cũng là ràng buộc, phải không? Cả hai câu trả lời đều hữu ích, theo ý kiến ​​của tôi. – WGH

+0

@WGH: bạn nói đúng, hành vi này được ghi lại cho các ổ cắm Windows (Lưu ý: Nếu một socket được mở ra, một cuộc gọi setsockopt được thực hiện, và sau đó một cuộc gọi sendto được thực hiện, Windows Sockets thực hiện một cuộc gọi hàm liên kết ngầm). 'không chắc chắn đây là trường hợp cho việc triển khai khác. Hơn nữa, ý kiến ​​của tôi về các cuộc gọi ngầm là nó là một thói quen xấu. – claf

0

Tôi phải thiếu điều gì đó, tại sao bạn không sử dụng ổ cắm udp để gửi dữ liệu trở lại? Bắt đầu với sendto và sau đó sử dụng chức năng recvfrom để đọc dữ liệu đến cũng bạn nhận được như một tiền thưởng địa chỉ mà từ đó dữ liệu đã được gửi, ngay tại đó để bạn gửi trả lời lại.

+0

Một số giao thức yêu cầu bạn quan tâm đến số cổng nào bạn đang sử dụng. Ví dụ: khách hàng [TFTP] (http://tools.ietf.org/html/rfc1350) sử dụng nó để phân biệt giữa nhiều lần truyền đồng thời từ cùng một máy chủ. Máy chủ không thể gửi lại từ cùng một cổng, mỗi lần truyền tệp yêu cầu máy chủ gửi từ cổng nguồn khác. Máy chủ không trả lời địa chỉ nguồn và cổng của máy khách như bạn đã phác thảo. – doug65536

+1

Trong ví dụ cụ thể của tôi, sử dụng một socket mới cho mỗi lần truyền, sau đó một cách mù quáng làm 'sendto' sẽ chọn một cổng nguồn, nhưng có thể có các giao thức khác mà bạn quan tâm đến số cổng trước khi thực sự thực hiện' sendto' . – doug65536

+0

@ doug65536 thats một ví dụ hợp lệ nhưng câu hỏi ban đầu không chứa bất kỳ chi tiết cụ thể nào về lý do. – Jonke

168

Tùy chọn khác là chỉ định cổng 0 đến bind(). Điều đó sẽ cho phép bạn liên kết với một địa chỉ IP cụ thể (trong trường hợp bạn có nhiều được cài đặt) trong khi vẫn liên kết với một cổng ngẫu nhiên. Nếu bạn cần biết cổng nào đã được chọn, bạn có thể sử dụng getsockname() sau khi thực hiện ràng buộc.

+18

Ràng buộc tới cổng 0 là cách được tài liệu chính thức để liên kết với một cổng ngẫu nhiên được gán cho hệ điều hành. –

+0

Tài liệu ở đâu? Không phải là tôi đang nói điều này sai, tôi muốn nhìn thấy một tuyên bố có thẩm quyền. –

+8

Nó nằm trong tài liệu ['bind()'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550.aspx): "nếu cổng được chỉ định là 0, dịch vụ Nhà cung cấp chỉ định một cổng duy nhất cho ứng dụng từ phạm vi cổng khách động.Trong Windows Vista và sau đó, phạm vi cổng máy khách động là một giá trị giữa 49152 và 65535. Đây là sự thay đổi từ Windows Server 2003 trở về trước. là một giá trị từ 1025 đến 5000 ... Ứng dụng có thể sử dụng getockname sau khi gọi liên kết để tìm hiểu địa chỉ và cổng đã được gán cho socket. " –

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