socket bind() 方法
阿新 • • 發佈:2019-02-02
名稱
bind()
把名字和套接字相關聯
使用格式
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t *addrlen);功能描述
當用socket()函式建立套接字以後,套接字在名稱空間(網路地址族)中存在,但沒有任何地址給它賦值。bind()把用addr指定的地址賦值給用檔案描述符代表的套接字sockfd。addrlen指定了以addr所指向的地址結構體的位元組長度。一般來說,該操作稱為“給套接字命名”。
通常,在一個SOCK_STREAM
備註:
呼叫bind()函式之後,為socket()函式建立的套接字關聯一個相應地址,傳送到這個地址的資料可以通過該套接字讀取與使用。
備註:
bind()函式並不是總是需要呼叫的,只有使用者程序想與一個具體的地址或埠相關聯的時候才需要呼叫這個函式。如果使用者程序沒有這個需要,那麼程式可以依賴核心的自動的選址機制來完成自動地址選擇,而不需要呼叫bind()函式,同時也避免不必要的複雜度。在一般情況下,對於伺服器程序問題需要呼叫bind()函式,對於客戶程序則不需要呼叫bind()函式。
套接字的命名規則在不同的網路協議族中有所不同。對於AF_INET
傳送給引數addr的實際結構依賴於網路協議族。sockaddr結構定義為如下格式:
[plain] view plain copy print?- struct sockaddr {
- sa_family_t sa_family;
- char sa_data[14];
- }
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
該結構的唯一目的是強制結構指標在addr引數中傳送,以避免編譯過程出現warning。參看如下例項。
返回值
成功,返回0;出錯,返回-1,相應地設定全域性變數errno。
錯誤
EACCESS
地址空間受保護,使用者不具有超級使用者的許可權。
EADDRINUSE
給定的地址正被使用。
例項:
下面的例項演示瞭如何在UNIX域中繫結流套接字,並接收連線。
[plain] view plain copy print?- <span style="color:#3366ff;">#include <sys/socket.h>
- #include <sys/un.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #define MY_SOCK_PATH "/somepath"
- #define LISTEN_BACKLOG 50
- #define handle_error(msg) \
- do { perror(msg); exit(EXIT_FAILURE); } while (0)
- int
- main(int argc, char *argv[])
- {
- int sfd, cfd;
- struct sockaddr_un my_addr, peer_addr;
- socklen_t peer_addr_size;
- sfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sfd == -1)
- handle_error("socket");
- memset(&my_addr, 0, sizeof(struct sockaddr_un));
- /* Clear structure */
- my_addr.sun_family = AF_UNIX;
- strncpy(my_addr.sun_path, MY_SOCK_PATH,
- sizeof(my_addr.sun_path) - 1);
- if (bind(sfd, (struct sockaddr *) &my_addr,
- sizeof(struct sockaddr_un)) == -1)
- handle_error("bind");
- if (listen(sfd, LISTEN_BACKLOG) == -1)
- handle_error("listen");
- /* Now we can accept incoming connections one
- at a time using accept(2) */
- peer_addr_size = sizeof(struct sockaddr_un);
- cfd = accept(sfd, (struct sockaddr *) &peer_addr,
- &peer_addr_size);
- if (cfd == -1)
- handle_error("accept");
- /* Code to deal with incoming connection(s)... */
- /* When no longer required, the socket pathname, MY_SOCK_PATH
- should be deleted using unlink(2) or remove(3) */
- }</span>
int connect(client_sock,(struct sockaddr *)&serv_addr, sizeof(serv_addr)); 客戶端建立socket, 地址相關的繫結系統會預設完成。 最重要的是完善client端 server socket的配置,因為UDP中,目的才是最重要的。
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MY_SOCK_PATH "/somepath"
#define LISTEN_BACKLOG 50
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
int sfd, cfd;
struct sockaddr_un my_addr, peer_addr;
socklen_t peer_addr_size;
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1)
handle_error("socket");
memset(&my_addr, 0, sizeof(struct sockaddr_un));
/* Clear structure */
my_addr.sun_family = AF_UNIX;
strncpy(my_addr.sun_path, MY_SOCK_PATH,
sizeof(my_addr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &my_addr,
sizeof(struct sockaddr_un)) == -1)
handle_error("bind");
if (listen(sfd, LISTEN_BACKLOG) == -1)
handle_error("listen");
/* Now we can accept incoming connections one
at a time using accept(2) */
peer_addr_size = sizeof(struct sockaddr_un);
cfd = accept(sfd, (struct sockaddr *) &peer_addr,
&peer_addr_size);
if (cfd == -1)
handle_error("accept");
/* Code to deal with incoming connection(s)... */
/* When no longer required, the socket pathname, MY_SOCK_PATH
should be deleted using unlink(2) or remove(3) */
}