简单分析一下socket中的bind

在最开始接触bind的时候,只是在写基于tcp的server端的时候,知道在listen之前需要先bind一下,用来确保socket能在某个固定的端口监听。而bind的时候,函数参数中的端口填自己将要绑定的端口就行;而IP地址,需要填本机的IP,但是也可以用一个宏INADDR_ANY代替,用这个宏就可以不用查找本机的IP,它就可以代替本机的IP。当时只觉得这个INADDR_ANY比较神奇,但是由于当时觉得用起来很方便,也没出啥问题,也就没有再深究。
  但是最近在做RTSP服务器的时候,有种特殊的应用,导致我不得不对bind这个函数仔细地看一下。
  我们知道无论是UDP还是TCP,socket都会与一个本地的IP和端口想对应,我们往往把这个IP和端口称之为socket的源地址和源端口。当我们作为客户端利用socket去发送数据时,很少会去考虑这个源地址和源端口到底是什么,我们更关心的是它的目的地址和端口。我们往往只有在监听的时候,才去考虑这个源端口,所以我们在监听的时候会去用bind。当我们bind之后,内核就会将这个socket的源端口锁定到我们设定的端口上。但是这就有一个问题,这个bind绑定端口,是将本来没有源端口的socket绑定到我们指定的端口上,还是将一个已经分配了端口的socket重定向到我们指定的端口上呢?
  在《UNIX网络编程》这本书中提到:“如果一个TCP客户或者服务器未曾调用bind捆绑一个端口,当调用connect或listen时,内核就要为相应的套接字选择一个临时接口。”从这句话中可以判断出,其实在调用socket函数创建socket时,内核还并未给socket分配源地址和源端口。而对于UDP,我猜测在调用sendto发送数据时,在未捆绑端口的情况下,内核也会随机分配端口。
  而我遇到的特殊应用要求我在用UDP发送数据之前要告诉对方我的发送端口,这也就意味着我在sendto之前必须要捆绑端口,因此我在发送数据之前就得调用bind函数绑定一下端口了。但是我就在想内核既然有随机分配端口的能力,而我需要的也只是让它绑定一下而不用绑定在固定端口的业务,socket中应该能够提供这种业务。然后果然我发现bind就具备这种能力,当bind的参数中端口地址为0的时候,这时候就是由内核分配端口。这样我就不用考虑端口地址重复的问题,而放心的把这个问题交给内核处理了。

  就在发现bind的这个机制的同时,我发现其实bind对于源地址也同样具备这种处理方式,当系统具有多IP(多网卡)的情况,当我们把bind函数中的ip参数置0时,就是由内核自己选择分配IP。而之前一直觉得很神奇的INADDR_ANY其实一点也不神奇,它的值其实就是0。所以当我们只有单一IP的时候,我们就可以用INADDR_ANY去代替那个单一的IP,因为内核分配的时候只能选择这一个IP。从而造成了INADDR_ANY就是本机IP的现象。

====

http://www.cnblogs.com/nightwatcher/archive/2011/07/03/2096717.html


----

NAME
bind - bind a name to a socket
SYNOPSIS

#include <sys/socket.h>

int bind(int
socket, const struct sockaddr *address,
       socklen_t
address_len);

DESCRIPTION

The bind() function shall assign a local socket address address to a socket identified by descriptor socketthat has no local socket address assigned. Sockets created with the socket() functionare initially unnamed; they are identified only by their address family.

The bind() function takes the following arguments:

socket
Specifies the file descriptor of the socket to be bound.
address
Points to a sockaddr structure containing the address to be bound to the socket. The length and format of the addressdepend on the address family of the socket.
address_len
Specifies the length of the sockaddr structure pointed to by the address argument.

The socket specified by socket may require the process to have appropriate privileges to use the bind()function.

RETURN VALUE

Upon successful completion, bind() shall return 0; otherwise, -1 shall be returned and errno set to indicate theerror.

ERRORS

The bind() function shall fail if:

[EADDRINUSE]
The specified address is already in use.
[EADDRNOTAVAIL]
The specified address is not available from the local machine.
[EAFNOSUPPORT]
The specified address is not a valid address for the address family of the specified socket.
[EBADF]
The socket argument is not a valid file descriptor.
[EINVAL]
The socket is already bound to an address, and the protocol does not support binding to a new address; or the socket has beenshut down.
[ENOTSOCK]
The socket argument does not refer to a socket.
[EOPNOTSUPP]
The socket type of the specified socket does not support binding to an address.

If the address family of the socket is AF_UNIX, then bind() shall fail if:

[EACCES]
A component of the path prefix denies search permission, or the requested name requires writing in a directory with a mode thatdenies write permission.
[EDESTADDRREQ] or [EISDIR]
The address argument is a null pointer.
[EIO]
An I/O error occurred.
[ELOOP]
A loop exists in symbolic links encountered during resolution of the pathname in address.
[ENAMETOOLONG]
A component of a pathname exceeded {NAME_MAX} characters, or an entire pathname exceeded {PATH_MAX} characters.
[ENOENT]
A component of the pathname does not name an existing file or the pathname is an empty string.
[ENOTDIR]
A component of the path prefix of the pathname in address is not a directory.
[EROFS]
The name would reside on a read-only file system.

The bind() function may fail if:

[EACCES]
The specified address is protected and the current user does not have permission to bind to it.
[EINVAL]
The address_len argument is not a valid length for the address family.
[EISCONN]
The socket is already connected.
[ELOOP]
More than {SYMLOOP_MAX} symbolic links were encountered during resolution of the pathname in address.
[ENAMETOOLONG]
Pathname resolution of a symbolic link produced an intermediate result whose length exceeds {PATH_MAX}.
[ENOBUFS]
Insufficient resources were available to complete the call.
====

http://pubs.opengroup.org/onlinepubs/009695399/functions/bind.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值