2012-10-06 31 views
34

Tôi muốn biết hàm chính xác của bind() trong TCP. Có nghĩa là gì bằng cách 'ràng buộc' một địa chỉ cục bộ vào socket? Nếu nó gán một số cổng vào socket, thì tại sao chúng ta không sử dụng nó trong máy khách? Tôi biết rằng cổng được gán bởi hệ điều hành tự động ở phía khách hàng, nhưng tôi không nhận được bức tranh lớn về cách tất cả các công trình này hoạt động.Tại sao bind() được sử dụng trong TCP? Tại sao nó chỉ được sử dụng trên phía máy chủ và không phải ở phía khách hàng?

Sau khi liên kết(), chúng tôi lắng nghe(). Làm thế nào là liên kết liên quan đến listen()? Liệu listen() có biết rằng bind() đã được thực thi không? Nếu vậy, những thay đổi nào ràng buộc() làm sao cho nó được biết? Tôi có nghĩa là, làm thế nào để trở về số không để thực hiện thành công giúp đỡ?

Tôi đã trải qua nhiều định nghĩa, nhưng không có nơi nào tôi có thể nhận được tất cả điều này một cách chi tiết. Vì vậy, nếu bất cứ ai có thể vui lòng giải thích điều này với tôi, tôi sẽ biết ơn.

Trả lời

14

Nó gán số cổng cuối của "địa phương".

Đối với ổ cắm máy chủ, đây là cách cuối cùng cần thực hiện - đó chính xác là những gì cần: có ổ cắm của bạn bị ràng buộc với cổng 80 cho máy chủ web chẳng hạn. Tuy nhiên,

Đối với ổ cắm máy khách, địa chỉ và cổng cục bộ thường không quan trọng. Vì vậy, bạn không phải bind(). Nếu máy chủ hạn chế khách hàng của mình có thể có một số cổng nhất định hoặc số cổng trong một phạm vi nhất định, bạn cũng có thể sử dụng bind() trên phía máy khách.

Mặt khác, bạn cũng có thể listen() trên ổ cắm nơi bạn chưa gọi bind() (thực ra tôi không chắc chắn về điều đó, nhưng nó sẽ có ý nghĩa). Trong trường hợp này, cổng máy chủ của bạn sẽ là ngẫu nhiên, và quá trình máy chủ sẽ giao tiếp cổng của nó thông qua một phương tiện khác nhau cho khách hàng. Hãy tưởng tượng một giao thức "kết nối kép" như FTP, nơi bạn có kết nối điều khiển và kết nối dữ liệu. Cổng kết nối dữ liệu lắng nghe hoàn toàn tùy ý, nhưng phải được truyền đạt sang phía bên kia. Vì vậy, "cổng được xác định tự động" được sử dụng và truyền đạt.

Một ví dụ bằng Python:

import socket 
s = socket.socket() # create your socket 
s.listen(10) # call listen without bind 
s.getsockname() Which random port number did we get? 
# here results in ('0.0.0.0', 61372) 

s2 = socket.socket() # create client socket 
s2.connect(('localhost', 61372)) # connect to the one above 
s3, x = s.accept() # Python specific use; s3 is our connected socket on the server side 
s2.getpeername() 
# gives ('127.0.0.1', 61372) 
s2.getsockname() 
# gives ('127.0.0.1', 54663) 
s3.getsockname() 
# gives ('127.0.0.1', 61372), the same as s2.getpeername(), for symmetry 
s3.getpeername() 
#gives ('127.0.0.1', 54663), the same as s2.getsockname(), for symmetry 
#test the connection 
s2.send('hello') 
print s3.recv(10) 
+1

câu trả lời này không đầy đủ vì nó cũng chịu trách nhiệm về giao diện mạng để nghe qua địa chỉ ip, ví dụ: '0.0.0.0' – user3338098

7

Nó "liên kết" một ổ cắm với một địa chỉ, nếu không nó không biết địa chỉ nào (cặp địa chỉ ip/cổng) cần nghe.

bind cũng có thể được sử dụng ở phía máy khách. Một ví dụ là trên máy tính có nhiều thẻ mạng được kết nối với cùng một mạng, nhưng máy khách chỉ muốn được xem như đến từ một địa chỉ mạng cụ thể.

Ràng buộc không chỉ được sử dụng cho các cổng TCP, mà còn cho các ổ cắm UDP và các giao thức khác nữa.

8

bind() xác định cổng và giao diện địa phương địa chỉ cho kết nối. connect() thực hiện một ngụ ý bind("0.0.0.0", 0) nếu trước đó chưa được thực hiện (với số không được coi là "bất kỳ").

Đối với các kết nối gửi đi, điều này thường được chấp nhận và được ưu tiên. Hệ điều hành sẽ chỉ liên kết với "tất cả các giao diện" và chọn một số cổng không được sử dụng, số cao. Bạn chỉ cần ràng buộc trên máy khách nếu máy chủ dự kiến ​​bạn sẽ đến từ một cổng cụ thể hoặc một dải cổng. Một số dịch vụ chỉ cho phép kết nối từ số cổng nhỏ hơn 1024, những kết nối này chỉ có thể được liên kết bởi siêu người dùng, mặc dù điều đó không có nghĩa là nhiều ngày nay mọi người kiểm soát máy của riêng họ.

Đối với các kết nối đến, bạn phải liên kết với một cổng đã biết để khách hàng biết địa chỉ liên hệ với bạn.Một khi họ làm như vậy, họ đã cung cấp cho máy chủ địa chỉ/cổng địa phương của họ để thông tin liên lạc sau đó có thể chảy theo cả hai hướng. listen() sẽ chỉ hoạt động sau cuộc gọi bind().

Tất cả các ổ cắm phải được liên kết, cho dù chúng là UDP, TCP hay khác. Nó không phải lúc nào cũng được thực hiện một cách rõ ràng.

+1

" 'listen()' sẽ chỉ hoạt động sau một cuộc gọi 'bind()'. " Không, như bạn có thể thấy trong [ví dụ của tôi] (http://stackoverflow.com/a/12763313/296974). – glglgl

+1

Nếu nó hoạt động, thì 'bind()' là ngầm định và chọn một số cổng bán ngẫu nhiên liên kết với tất cả các giao diện. Điều này thường không hữu ích (mặc dù có những ngoại lệ hiếm). –

+0

Đúng vậy. – glglgl

0

Tôi biết đây là một câu hỏi cũ, nhưng tôi có một câu trả lời mới :)

Bạn có thể muốn kết nối đến một máy chủ mà chỉ cho phép một số lượng hạn chế các kết nối đến mỗi ip.

Nếu bạn có nhiều thẻ giao diện mạng (và do đó nhiều ip đi có thể kết nối từ), bạn có thể sử dụng bind(), manuallying đi xe đạp qua từng ip của bạn, để cân bằng kết nối của bạn, và do đó có nhiều lần nhiều kết nối như được cho phép.

Để có danh sách giao diện và ips của bạn, hãy xem câu trả lời this.

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