2012-10-06 54 views
34

Quería saber la función exacta de bind() en TCP. ¿Qué significa 'enlazar' una dirección local al socket? Si está asignando un número de puerto al socket, ¿por qué no lo usamos en el cliente? Sé que el OS asigna el puerto automáticamente en el lado del cliente, pero no entiendo muy bien cómo funciona todo esto.¿Por qué se usa bind() en TCP? ¿Por qué se usa solo en el servidor y no en el lado del cliente?

Después de bind(), escuchamos(). ¿Cómo se relaciona el enlace con listen()? ¿Escuchará() que bind() se ha ejecutado? Si es así, ¿qué cambios hace bind() para que se sepa? Quiero decir, ¿cómo ayuda devolver cero para una ejecución exitosa?

He pasado por muchas definiciones, pero no he podido obtener todo esto en detalle. Entonces, si alguien puede explicarme esto por favor, lo agradeceré.

Respuesta

14

Asigna el número de puerto del extremo "local".

Para un socket de servidor, este es el mejor camino a seguir: es exactamente lo que se necesita: tener su socket vinculado al puerto 80 para un servidor web, por ejemplo.

Para un socket de cliente, sin embargo, la dirección local y el puerto normalmente no son importantes. Entonces no lo haces bind(). Si el servidor restringe a sus clientes para que tal vez tengan un cierto número de puerto o un número de puerto fuera de un rango determinado, también puede usar bind() en el lado del cliente.

Por otro lado, es posible que también pueda listen() en un socket donde no ha llamado al bind() (en realidad no estoy seguro de eso, pero tendría sentido). En este escenario, el puerto de su servidor sería aleatorio y el proceso del servidor comunicaría su puerto a través de un medio diferente al cliente. Imagine un protocolo de "doble conexión" como FTP, donde tiene una conexión de control y una conexión de datos. El puerto en el que se escucha la conexión de datos es completamente arbitrario, pero debe comunicarse al otro lado. Por lo tanto, el "puerto determinado automáticamente" se usa y se comunica.

Un ejemplo en 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

esta respuesta es incompleta, ya que también es responsable de las interfaces de red para escuchar a través de una dirección IP, p. '0.0.0.0' – user3338098

7

"une" un socket a una dirección; de lo contrario, no sabe qué dirección (par de dirección IP/puerto) debe escuchar.

Y bind también puede usarse en el lado del cliente. Un ejemplo es en una computadora con varias tarjetas de red conectadas a la misma red, pero el cliente solo quiere que se lo vea como proveniente de una dirección de red específica.

La vinculación no solo se utiliza para los sockets TCP, sino también para los sockets UDP y otros protocolos.

8

bind() define la dirección del puerto y de interfaz local para la conexión. connect() hace un implícito bind("0.0.0.0", 0) si uno no se ha hecho previamente (con cero tomando como "cualquiera").

Para las conexiones salientes, esto es generalmente aceptable y preferido. El sistema operativo simplemente enlazará a "todas las interfaces" y elegirá un puerto no utilizado de alta numeración. Solo necesita vincular al cliente si el servidor espera que provenga de un puerto o rango de puertos específico. Algunos servicios solo permiten conexiones desde números de puerto inferiores a 1024, los únicos que el superusuario puede vincular, aunque eso no significa mucho ahora que todo el mundo controle su propia máquina.

Para las conexiones entrantes, debe vincular a un puerto conocido para que los clientes sepan dónde comunicarse con usted.Una vez que lo hacen, le han dado al servidor su dirección/puerto local para que la comunicación fluya en ambas direcciones. listen() solo funcionará después de una llamada bind().

Todos los sockets deben vincularse, ya sean UDP, TCP u otros. Simplemente no siempre está hecho explícitamente.

+1

" 'listen()' solo funcionará después de una llamada 'bind()'. " No, como puede ver en [mi ejemplo] (http://stackoverflow.com/a/12763313/296974). – glglgl

+1

Si funciona, entonces 'bind()' es implícito y elige un número de puerto semialeatorio enlazado a todas las interfaces. Esto no es generalmente útil (aunque hay raras excepciones). –

+0

Eso es correcto, sin embargo. – glglgl

0

Sé que esto es una vieja pregunta, pero tengo una nueva respuesta :)

Es posible que desee conectarse a un servidor que sólo permite un número limitado de conexiones entrantes por ip.

Si tiene varias tarjetas de interfaz de red (y por lo tanto múltiples ips salientes posibles para conectarse), puede usar bind(), ciclismo manual a través de cada una de sus ips, para equilibrar sus conexiones, y así tener varias veces tantas conexiones como se permitirían de otra manera.

Para obtener una lista de sus interfaces y ips, consulte this answer.

Cuestiones relacionadas