1. 程式人生 > >socket bind() 方法

socket bind() 方法


名稱

bind()

把名字和套接字相關聯

使用格式

#include <sys/types.h>

#include <sys/socket.h>

int bind(int sockfd,const struct sockaddr *addr,socklen_t *addrlen);

功能描述

當用socket()函式建立套接字以後,套接字在名稱空間(網路地址族)中存在,但沒有任何地址給它賦值。bind()把用addr指定的地址賦值給用檔案描述符代表的套接字sockfdaddrlen指定了以addr所指向的地址結構體的位元組長度。一般來說,該操作稱為“給套接字命名”。

通常,在一個SOCK_STREAM

套接字接收連線之前,必須通過bind()函式用本地地址為套接字命名。

備註:

呼叫bind()函式之後,為socket()函式建立的套接字關聯一個相應地址,傳送到這個地址的資料可以通過該套接字讀取與使用。

備註:

bind()函式並不是總是需要呼叫的,只有使用者程序想與一個具體的地址或埠相關聯的時候才需要呼叫這個函式。如果使用者程序沒有這個需要,那麼程式可以依賴核心的自動的選址機制來完成自動地址選擇,而不需要呼叫bind()函式,同時也避免不必要的複雜度。在一般情況下,對於伺服器程序問題需要呼叫bind()函式,對於客戶程序則不需要呼叫bind()函式。

套接字的命名規則在不同的網路協議族中有所不同。對於AF_INET

參看ip(),對於AF_INET6參看ipv6(),對於AF_INET6參看unix(),對於AF_APPLETALK參看ddp(),對於AF_APPLETALK參看packet(),對於AF_X25參看x25(),對於AF_NETLINK參看netlink()。

傳送給引數addr的實際結構依賴於網路協議族。sockaddr結構定義為如下格式:

[plain] view plain copy print?
  1. struct sockaddr {  
  2.     sa_family_t     sa_family;  
  3.     char            sa_data[14];  
  4. }  
struct sockaddr {
    sa_family_t     sa_family;
    char            sa_data[14];
}

該結構的唯一目的是強制結構指標在addr引數中傳送,以避免編譯過程出現warning。參看如下例項。

返回值

成功,返回0;出錯,返回-1,相應地設定全域性變數errno。

錯誤

EACCESS

地址空間受保護,使用者不具有超級使用者的許可權。

EADDRINUSE

給定的地址正被使用。

例項:

下面的例項演示瞭如何在UNIX域中繫結流套接字,並接收連線。

[plain] view plain copy print?
  1. <span style="color:#3366ff;">#include <sys/socket.h>  
  2. #include <sys/un.h>  
  3. #include <stdlib.h>  
  4. #include <stdio.h>  
  5. #include <string.h>  
  6. #define MY_SOCK_PATH "/somepath"  
  7. #define LISTEN_BACKLOG 50  
  8. #define handle_error(msg) \  
  9.     do { perror(msg); exit(EXIT_FAILURE); } while (0)  
  10. int  
  11. main(int argc, char *argv[])  
  12. {  
  13.     int sfd, cfd;  
  14.     struct sockaddr_un my_addr, peer_addr;  
  15.     socklen_t peer_addr_size;  
  16.    sfd = socket(AF_UNIX, SOCK_STREAM, 0);  
  17.     if (sfd == -1)  
  18.         handle_error("socket");  
  19.    memset(&my_addr, 0, sizeof(struct sockaddr_un));  
  20.                         /* Clear structure */  
  21.     my_addr.sun_family = AF_UNIX;  
  22.     strncpy(my_addr.sun_path, MY_SOCK_PATH,  
  23.             sizeof(my_addr.sun_path) - 1);  
  24.    if (bind(sfd, (struct sockaddr *) &my_addr,  
  25.             sizeof(struct sockaddr_un)) == -1)  
  26.         handle_error("bind");  
  27.    if (listen(sfd, LISTEN_BACKLOG) == -1)  
  28.         handle_error("listen");  
  29.    /* Now we can accept incoming connections one  
  30.        at a time using accept(2) */  
  31.    peer_addr_size = sizeof(struct sockaddr_un);  
  32.     cfd = accept(sfd, (struct sockaddr *) &peer_addr,  
  33.                  &peer_addr_size);  
  34.     if (cfd == -1)  
  35.         handle_error("accept");  
  36.    /* Code to deal with incoming connection(s)... */  
  37.    /* When no longer required, the socket pathname, MY_SOCK_PATH  
  38.        should be deleted using unlink(2) or remove(3) */  
  39. }</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) */
}