linux c 網絡編程, 常用網絡函數,範例

hstrerror返回網絡錯誤原因的描述字符串
相關函數:herror
表頭文件:#include <netdb.h>
函數定義:const char *hstrerror(int err)
函數說明:hstrerror()用來依參數err的錯誤代碼來查詢socket錯誤原因的描述字符串, 然後將該字符串指針返回
返回值   :返回描述錯誤原因的字符串指針
範例:
/*顯示錯誤代碼0到5的錯誤原因描述*/
**#include <netdb.h>**
main()
{
    int i;
    for(i=0; i<6; i++)
          printf("%d: %s\n", i, hstrerror(i));
}
herror指印出網絡錯誤原因信息字符串
相關函數:hstrerror
表頭文件:#include <netdb.h>
函數定義:void  herror(const char *s);
函數說明:herror()用來將上一個網絡函數發生錯誤的原因輸出到標準錯誤stderr。參數s所指的字符串會先打印出, 後面再加上錯誤的原因字符串。此錯誤原因系依照全局變量h_errno的值來決定要輸出的字符串
返回值  :無
範例:參perror()
htons將16位主機字符順序轉換成網絡字符順序
相關函數:htonl, ntonl, ntohs
表頭文件:#include <netinet/in.h>
函數定義:unsigned short int htons(unsigned short int hostshort)
函數說明:htons()用來將參數指定的16位hostshort轉換成網絡字符順序
返回值   :返回對應的網絡字符順序
範例:參getservbyport()   connect()
htonl將32位主機字符順序轉換成網絡字符順序
相關函數:htons, ntohl, ntohs
表頭文件:#include <netinet/in.h>
函數定義:unsigned long int htonl(unsigned long int hostlong)
函數說明:htonl()用來將參數指定的32位hostlong轉換成網絡字符順序
返回值   :返回對應的網絡字符順序
範例:參getservbyport()  connect()
inet_aton將網絡地址轉成網絡二進制的數字
相關函數:inet_addr, inet_ntoa
表頭文件:#include <sys/socket.h>
               #include <netinet/in.h>
               #include <arpa/inet.h>
函數定義:int inet_aton(const char *cp, struct in_addr *inp)
函數說明:inet_aton()用來將參數cp所指的網絡地址字符串轉成網絡所使用的二進制的數字,然後存於參數inp所指的in_addr結構中
struct in_addr
{ 
        unsigned long int s_addr;   //數字和點組成的字符串,如192.168.0.239
}
返回值  :成功則返回非0值 , 失敗則返回0
inet_addr將網絡地址轉成網絡二進制的數字
相關函數:inet_aton, inet_ntoa
表頭文件:#include <sys/socket.h>
               #include <netinet/in.h>
               #include <arpa/inet.h>
函數定義:unsigned long int inet_addr(const char *cp)
函數說明:inet_addr()用來將參數cp所指的網絡地址字符串轉成網絡所使用的二進制的數字。網絡地址字符串是以數字和點組成的字符串,如192.168.0.236
返回值  : 成功則返回對應的網絡二進制的數字,失敗返回-1
listen等待連接
相關函數:socket, bind, accpet, connect
表頭文件:#include <sys/socket.h>
函數定義:int listen(int s, int backlog)
函 數說明:listen()用來等待參數s的socket連線。參數backlog指定同時能處理的最大連接要求,如果連接數目達到此上限則client端 將收到ECONNREFUSED的錯誤(請參connect())。 listen()並未開始接受連線,只是設置socket爲listen模式,真正接受client()端連線的是accept()。通常 listen()會在socket()、bind()之後調用,接着才調用accept()
附加說明:listen()只適用SOCK_STREAM或SOCK_SEQPACKET的socket類型.如果socket爲AF_INET則參數backlog最大值可設到128
返回值  :成功則返回0, 失敗則返回-1, 錯誤原因存於errno中
錯誤代碼:EBADF              參數sockfd非合法socket處理代碼
               EACCESS           權限不足
               EOPNOTSUPP    指定的socket並未支援listen模式
範例:
/*
利用socket的TCP server此程序會接收由TCP client傳來的字符串並顯示
TCP client範例請參connect()
*/

**

 - #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
 - **列表內容**

    #include <arpa/inet.h>
    #include <unistd.h>
    #define PROT                 1234   /*使用port號碼*/
    #define MAXSOCKFD        10     /*可同時服務的最大連線數目*/

**

main()
{
    int sockfd, newsockfd, is_connected[MAXSOCKFD], fd;
    struct sockaddr_in addr;
    int addr_len =sizeof(struct sockaddr_in);
    
    fd_set  readfds;
    char msg[]="Welcome to server!";
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <0)
    {
         perror("socket");
         exit(1);
    }

/*填寫sockaddr_in結構*/
hzero(&addr, sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockfd, &addr, sizeof(addr)) <0)
{
    perror("connect");
    exit(1);
}

if(listen(sockfd, 3)<0)
{
    perror("listen");
    exit(1);
}


/*清除連線狀態旗標*/
for(fd=0; fd<MAXSOCKFD; fd++)
     is_connected[fd]=0;

while(1)
{
           FD_ZERO(&readfds);
           FD_SET(sockfd, &readfds);
}

for(fd=0; fd<MAXSOCKFD; fd++)
{
   if(is_connected[fd])  
         FD_SET(fd, &readfds);   
}


if(!select(MAXSOCKFD, &readfds, NULL, NULL, NULL)) 
        continue;

/*判斷是否有新連接或新信息進來*/

for(fd=0;, fd<MAXSOCKFD; fd++)
{
    if(FD_ISSET(fd, &readfds))
    {
         if(sockfd == fd)
         {
                /*接收新連接*/
                if((newsockfd = accept(sockfd, &addr, &addr_len)) < 0 )
                        perror("accept");

                /*將歡迎字符串傳給cient*/
                write(newsockfd, msg, sizeof(msg) );

                is_connected(newsockfd) = 1;
                printf("Connect from %s\n", inet_ntoa(addr.sin_addr));           
         }/*:: if(sockfd == fd)*/
         else
         {
             /*接收新信息*/
            bzero(buffer, sizeof(buffer));
           
            if(read(fd, buffer, sizeof(buffer)) <=0)
            {
                   /*連接已中斷,清除連接狀態標誌*/
                   printf("Connection closed.\n");
                   is_connected[fd]=0;
                   close(fd);
            }
            else
            {
                   printf("%s", buffer);
            }
         }/*::else- if(sockfd == fd)*/

    }/*:: if(FD_ISSET(fd, &readfds))*/

}/*::for(fd=0;, fd<MAXSOCKFD; fd++)*/

}/*::main()*/
inet_ntoa將網絡二進制的數字轉成網絡地址
相關函數:inet_addr, inet_aton
表頭文件:#include <sys/socket.h>
               #include <netinet/in.h>
               #include <arpa/inet.h>
函數定義:char *inet_ntoa(struct in_addr in)
函數說明:inet_ntoa()用來將參數in所指的網絡二進制數字轉成網絡地址,然後將指向此網絡地址字符串的指針返回
struct in_addr
{
        unsigned long int s_addr; //以點和數字組成的IP地址
}
返回值 :成功則返回字符串指針, 失敗則返回NULL
範例:參connect()
ntohl將32位網絡字符順序轉換成主機字符順序
相關函數:htonl, htons, ntohs
表頭文件:#include <netinet/in.h>
函數定義:unsigned long int ntohl(unsigned long int netlong)
函數說明:l將32位網絡字符順序轉換成主機字符順序
返回值   :返回對應的主機字符順序
範例      :參getservent()
ntohs將16位網絡字符順序轉換成主機字符順序
相關函數:htonl, htons, ntohl
表頭文件:#include <netinet/in.h>
函數定義:unsigned short int ntohs(unsigned short int netshort)
函數說明:將16位網絡字符順序轉換成主機字符順序
返回值   :返回對應的主機字符順序
範     例 :參getservent()
recvfrom經socket接收數據
相關函數:recv, recvmsg, send, sendto, socket
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int recvfrom(int s, void *buf, int len, unsigned int flags,  struct sockaddr *from, int *fromlen)
函 數說明:recv()用來接收遠程主機經指定的socket傳來的數據,並把數據存到由參數buf指向的內存空間,參數len爲可接收數據的最大長度。參 數flags一般設爲0, 其他參數值定義參考recv()。 參數from用來指定欲傳送的網絡地址,結構sockaddr請參考bind(). 參數fromlen爲sockaddr的結構長度
返回值 :成功則返回接收到的字符數, 失敗則返回-1, 錯誤原因存於errno中
錯誤代碼:
EBADF               參數s非合法的socket處理代碼
EFAULT             參數中有一指針指向無法存取的內存空間
ENOTSOCK        參數s爲一文件描述詞,非socket
EINTR               被信號所中斷
EAGAIN             此動作會令進程阻斷, 但參數s的socket爲不可阻斷
ENOBUFS           系統的緩衝內存不足
ENOMEM            核心內存不足
EINVAL              傳給系統調用的參數不正確

範例:
/*利用socket的UDP client 此程序會連線UDP server, 並將鍵盤輸入的字符串傳送給server UDP server範例請參考sendto()*/

 - #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
 - 列表內容

    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #define PORT   2345   /*使用的port號碼*/
    #define SERVER_IP   "127.0.0.1"   /*server的IP*/

main()
{
    int s, len;
    struct sockadd_in addr;
    int addr_len = sizeof(struct sockaddr_in);
    char buffer[256];

    /*建立socket*/
   if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
   {
         perror("socket");
        exit(1);
   }

   /*填寫sockaddr_in結構*/
   bzero(&addr, sizeof(addr));
   addr.sin_family = AF_INET;
   addr.sin_port   = htons(PORT);
   addr.sin_addr.s_addr=inet_addr(SERVER_IP);

   while(1)
   {
        bzero(buffer, sizeof(buffer));

        /*從標準輸入設備取得字符串*/
        len = read(STDIN_FILENO, buffer, sizeof(buffer));

        /*將字符串傳送給server端*/
       sendto(s, buffer, len, o, &addr, addr_len);

       /*接收server端返回的字符串*/
       len = revfrom(s, buffer, sizeof(buffer), 0, &addr, &addr_len);
       
       printf("receive : %s", buffer);

   }/*while(1)*/

}/*::main()*/
recvmsg經socket接收數據
相關函數:recv, recvfrom, send, sendto, sendmsg, socket
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int recvmsg(int s, struct msgaddr *msg, unsigned int flags)
函數說明:recvmsg()用來接收遠程主機經指定的socket傳來的數據。
參數s爲已建立好連線的socket, 如果利用UDP協議則不需經過連線操作。
參數msg指向欲連線的數據結構內容,
參數flags一般設爲0,
關於結構msghdr的定義請參考sendmsg()
返回值   :成功則返回接收到的字符數,失敗返回-1, 錯誤原因存於errno中
錯誤代碼:參recv
範例:參recvfrom()
sendmsg經socket傳送數據
相關函數:send, sendto, recv, recvfrom, recvmsg, socket
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int sendmsg(int s, const struct msghdr *msg, unsigned int flags)
函數說明:本函數用來將數據由指定的socket傳給對方主機。
參數s爲已建立好連接的socket
如果利用UDP協議則不需要經過連接操作
參數msg指向欲連接的數據結構內容,參數flags一般默認爲0, 詳細參send()
結構msghdr定義如下

struct msghdr
{
    void *msg_name;                /*Address to send to /receive from */
    socklen_t  msg_namelen;     /*Length of address data*/
    struct iovec  *msg_iov;        /*Vector of data to send/recieve into */
    size_t msg_iovlen;               /*Number of elements in the vector*/
    void *msg_control;              /*Ancillary data*/
    size_t  msg_controllen;        /*Ancillary data buffer length*/
    int msg_flags;                     /*Flags on received message*/
};

返回值 : 成功則返回實際傳送出去的字符數, 失敗返回-1, 錯誤原因存於errno中
錯誤代碼:參recv()
範例    :參sendto()
sendto經socket傳送數據
相關函數:send, sendmsg, recv, recvfrom, socket
表頭文件:#include <sys/types.h>
               #incude <sys/socket.h>
函數定義:int sendto(int s, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen)
函數說明:本函數用來將數據由指定的socket傳給對方主機。
參數s爲已建立好連接的socket,如果利用UDP協議則不需經連接操作
參數msg指向欲連線的數據內容,
參數len則爲數據長度
參數flags一般設爲0,詳細參send()
參數to用來指定欲傳送的網絡 地址,結構sockaddr請參bind()
參數tolen爲sockaddr結構長度

返回值 :成功則返回實際傳送出去的字符數, 失敗返回-1, 錯誤原因存於errno中
錯誤代碼:參recv()

範例:
/*
  利用socket的UDP server 
  此程序會接收由UDP client傳來的字符串然後再傳送回client
  TCP client範例請參考 recvfrom()
*/

**

 - #include <sys/types.h>
   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <arpa/inet.h>
   #include <unistd.h>
   #define PORT 2345   /*使用的PORT號碼*/

**
main()
{
     int sockfd, len;
     struct sockaddr_in addr;
     int addr_len=sizeof(struct sockaddr_in);
     char buffer[256];

     /*建立socket*/
     if((sockfd = socket(AF_INET, SOCK_DGREM, 0))<0)
     {
          perror("socket");
          exit(1);
     }
     
     /*填寫sockaddr_in結構*/
     bzero(&addr, sizeof(addr));
    
     addr.sin_family=AF_INET;
     addr.sin_port=htons(PORT);
     addr.sin_addr.s_addr=htonl(INADDR_ANY);
    
     if(bind(sockfd, &addr, sizeof(addr)) < 0)
     {
           perror("connect");
           exit(1);
     }

     while(1)
      {
             /*接收client端傳來的字符串*/
             bzero(buffer, sizeof(buffer));
             len=recvfrom(sockfd, buffer, sizeof(buffer), 0 , &addr, &addr_len);
             
             /*顯示client端的網絡地址IP*/
             printf("receive from %s\n", inet_ntoa(addr.sin_addr));

             /*將字串返回給client端*/            
             sendto(sockfd, buffer, len, 0, &addr, addr_len);

      }/*::while(1)*/
     
}/*::main()*/
recv經socket接收數據
相關函數:recvfrom, recvmsg, send, sendto, socket
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int recv(int s, void *buf, int len, unsigned int flags)
函數說明:recv()用來接收遠端主機經指定的socket傳來的數據,並把數據存到由參數buf指向的內存空間,
參數len爲可接收數據的最大長度
參數flags一般設爲0,其他值設置如下:
       MSG_OOB                接收以out-of-band送出的數據
       MSG_PEEK               返回來的數據並不會在系統內刪除,如果再調用recv()會返回相同的數據內容
       MSG_WAITALL         強迫接受到len大小的數據後才能返回,除非有錯誤或信號產生
       MSG_NOSIGNAL        此操作不願被SIGPIPE信號中斷
返回值 :成功則返回接收到的字符數,失敗則返回-1, 錯誤原因存於errno中
錯誤代碼:
EBADF            參數s非合法的socket處理代碼
EFAULT          參數中有一指針指向無法存取的內存空間
ENOTSOCK     參數s爲一文件描述詞,非socket
EINTR            被信號所中斷
EAGAIN          此動作會令進程阻斷,但參數s的socket爲不可阻斷
ENOBUFS        系統的緩衝內存不足
ENOMEM         核心內存不足
EINVAL           傳給系統調用的參數不正確

範例    :參listen()
send經socket傳送數據
相關函數:sendto, sendmsg, recv, recvfrom, socket
表頭文件:#include <sys/types.h>
               #inlcude <sys/socket.h>
函數定義:int send(int s, const void *msg, int len, unsigned int flags)
函數說明:本函數用來把數據由指定的socket傳給對方主機。
參數s爲已建立好連線的socket
參數msg指向欲連線的數據內容,參數len則爲數據長度
參數flags一般設爲0 ,詳參recv

返回值 :成功則返回實際傳送出去的字符數, 失敗返回-1, 錯誤原因存於errno中 , 
錯誤代碼:參recv
範例:      參connect()
setprotoent打開網絡協議的數據文件
相關函數:getprotobyname, getprotobynumber, endprotoent
表頭文件:#include <netdb.h>
函數定義:void setprotoent(int stayopen)
函數說明:setprotoent()用來打開/etc/protocols, 如果參數stayopen值爲1, 則接下來的getprotobyname()或getprotobynumber()將不會自動關閉此文件
setservent打開主機網絡服務的數據文件
相關函數:getservent, getservbyname, getservbyport, endservent
表頭文件:#include <netdb.h>
函數定義:void setservent(int stayopen)
函數說明:本函數用來打開/etc/services如果參數stayopen值爲1,則接下來的getservbyname()或getservbyport()將不會自動關閉此文件
setsockopt設置socket狀態
相關函數:getsockopt
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int setsockopt(int s, int level, int optna,e, const void *optval, socklen_t optlen)
函數說明:\本函數用來設置參數s指定的插座的狀態。

參數level代表欲設置的網絡層,一般高成SOL_SOCKET以存取socket層
參數optname代表欲設置的選項,有下列幾種數據
SO_DEBUG                     打開或關閉排錯模式
SO_REUSEADDR              允許在bind()過程中本地地址可重複使用
SO_TYPE                       返回socket形態(如SOCK_STREAM)
SO_ERROR                     返回socket已發生的錯誤原因
SO_DONTROUTE            送出的數據包不要利用路由設備來傳輸
SO_BROADCAST             使用廣播方式傳送
SO_SNDBUF                   設置送出的暫存區大小
SO_RCVBUF                   設置接收的暫存區大小
SO_KEEPALIVE               定期確定連接是否已終止
SO_OOBINLINE              當接收到OOB(out-of-band)數據時會馬上送到標準輸入設備
SO_LINGER                    確保數據安全且可靠的傳送出去

參數optval代表欲設置的值 
參數optlen則爲optval的長度

附加說明:
                EBADF                   參數s並非合法的socket處理代碼
                ENOTSOCK            參數s爲一文件描述詞,非socket
                ENOPROTOOPT      參數optname指定的選項不正確
                EFAULT                 參數optval指針指向無法存取的內存空間

範例:參getsockopt()
socket建立一個socket通信
相關函數:accept, bind, connect, listen
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int socket(int domain, int type, int protocol)
函數說明:socket()用來建立一個新的socket,也一是向系統註冊,通知系統建立一通信端口。
參數domain指定使用何種的地址類型,完整的定義在/usr/include/bits/socket.h內,常見的定義如下 
PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL                UNIX進程通訊協議P
PF_INET/AF_INENT                                             IPV4網絡協議
PF_INET6/AF_INET6                                           IPv6網絡協議
PF_IPX/AF_IPX                                                   IPX-Novell協議
PF_NETLINK/AF_NETLINK                                    核心用戶接口裝置
PF_X25/AF_X25                                                  ITU-T X.25/ISO-8208協議
PF_AX25/AF_AX25                                              業餘無線AX.25協議
PF_ATMPVC/AF_ATMPVC                                     存取原始ATM PVCs
PF_APPLETALK/AF_APPLETALK                            Appletalk(DDP)協議
PF_PACKET/AF_PACKET                                      初級封包接口

參數type有下列幾種數值:
SOCK_STREAM                       提供雙向連續且可信賴的數據流,即TCP,支持OOB(out-of-band)機制。在所有數據傳送前必須使用connect()來建立連線狀態
SOCK_DGRAM                         使用不連續不可信賴的數據包連接
SOCK_SEQPACKET                  提供連續可信賴的數據包連接
SOCK_RAW                            提供原始網絡協議存取
SOCK_RDM                             提供可信賴的數據包連接
SOCK_PACKET                        提供和網絡驅動程序直接通信

返回值  :成功則返回socket處理代碼, 失敗則返回-1
錯誤代碼:
  EPROTONOSUPPORT            參數domain指定的類型不支持參數type或protocol指定的協議
  ENFILE                                核心內存不足, 無法建立新的socket結構
  EMFILE                                進程文件表溢出,無法再建立新的socket
  EACCESS                             權限不足,無法建立參數type或protocol指定的協議
  ENOBUFS/ENOMEM               內存不足
  EINVAL                                參數domain/type/protocol不合法

範例:參connect()
shutdown終止socket通信
相關函數:socket, connect
表頭文件:#include <sys/socket.h>
函數定義:int shutdown(int s, int how)
函數說明:用來終止參數s所指定的socket連接
參數s是連接中的socket處理代碼
參數how有下列幾種情況:
how=0            終止讀取操作
how=1            終止傳送操作
how=2            終止讀取及傳送操作
返回值 :成功返回0, 失敗返回-1, 錯誤原因存於errno
錯誤代碼:
               EBADF                  參數s不是有效的socket處理代碼
               ENOTSOCK            參數s爲一文件描述詞,非socket 
               ENOTCONN            參數s指定的socket並未連接

accept接受socket連線
相關函數:socket, bind, listen, connect
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int accept(int s, struct sockaddr *addr, int *addrlen)
函數說明:accept()用來接受參數s的socket連線。
參 數s的socket必需先經bind()、listen()函數處理過,當有連線進來是accept()會返回一個新的socket處理代碼,往後的數據 傳送與讀取就是經由新的socket處理,而原來參數s的socket能繼續使用accept()來接受新的連線要求。連線成功時,參數addr所指的結 構會被系統填入遠程主機的地址數據,參數addrlen爲sockaddr的結構長度。
返回值  :成功則返回socket處理代碼, 失敗則返回-1, 錯誤原因存於errno中
錯誤代碼:EBADF                      參數s非合法socket處理代碼
               EFAULT                    參數addr指針指向無法存取的內存空間
               ENOSTOCK               參數s爲一文件描述詞,非socket         
               EOPNOTSUPP           指定的socket並非SOCK_STREAM
               EPERM                      防火牆(firewall)拒絕此連線
               ENOBUFS                  系統的緩衝內存不足
               ENOMEM                   核心內存不足

範例:請參listen()
 bind對socket定位
相關函數:socket, accept, connect, listen
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
函數說明:bind()用來設置給參數sockfd的socket一個名稱。此名稱由參數my_addr指向一sockaddr結構, 對於不同的socket domain定義了一個通用的數據結構:

struct  sockaddr{
         unsigned  short  int  sa_family;   /* 爲調用socket()的domain參數,即AF_xxxx值 */
         char  sa_data[14];  /* 最多使用14個字符長度  */
};

此sockaddr結構會因使用不同的socket domain而有不同結構的定義,例如使用AF_INET domain, 其sockaddr結構定義便爲:
struct socketadd_in
{
     unsigned short int sin_family;   /*  即爲sa_family */
     uint16_t  sin_port;                 /* 爲使用的port編號 */
     struct  int_addr sin_addr;        /* 爲IP地址 */
     unsigned char sin_zero[8];      /* 未用 */
};


struct in_addr
{
      uint32_t  s_addr;
};


參數addrlen爲sockaddr的結構長度

返回值   :成功則返回0,  失敗則返回-1, 錯誤原因存於errno中

錯誤代碼:EBADF            參數sockfd非合法socket處理代碼
               EACCESS        權限不足
               ENOTSOCK     參數sockfd爲一文件描述詞,非socket

範例: 參listen()
connect建立socket連線
相關函數:socket, bind, listen
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
函數說明:connect()用來將參數sockfd的socket連到參數serv_addr指定的網絡地址。結構sockaddr請參bind()
返回值   :成功則返回0, 失敗返回-1, 錯誤原因存於errno中
錯誤代碼:EBADF        參數sockfd非合法socket處理代碼
               EFAULT      參數serv_addr指針指向無法存取的內存空間
               ENOTSOCK 參數sockfd爲一文件描述詞,非socket
               EISCONN    參數sockfd的socket已是連線狀態
               ECONNREFUSED  連線要求被server端拒絕
               ETIMEDOUT        企圖連線的操作超過限定時間仍未有響應
               ENETUNREACH     sockaddr結構的sa_family不正確
               EALREADY           socket爲不可阻斷且先前的連線操作還未完成

範例:
/* 
  利用socket的TCP client
   此程序會連線TCP server,並將鍵盤輸入的字符串傳送給server
   TCP server範例請參考listen()
*/

 - #include <sys/stat.h>
   #include <fcntl.h>
   #include <unistd.h>
   #include <sys/types.h>
   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <arpa/inet.h>
   #define  PORT    1234         /* 使用的port號碼 */
   #define SERVER_IP    "127.0.0.1"   /* SERVER 的IP*/

main()
{
    int s;
    struct sockaddr_in  addr;
    char buffer[256];
    if((s = socket(AF_INET, SOCK_STREAM, 0)) <0) {
        perror("socket");
        exit(1);
    }
   
    /*填寫sockaddr_in 結構*/
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr= inet_addr(SERVER_IP);
    
     /* 嘗試連線 */
     if(connect(s, &addr, sizeof(addr))<0) {
           perror("connect");
           exit(1);
      }

     /* 接收由server端傳來的信息 */
     recv(s, buffer, sizeof(buffer), 0);
     printf("%s\n", buffer);
     while(1){
             bzero(buffer, sizeof(buffer));
          
             /*  從標準輸入設備取得字符串 */     
             read(STDIN_FILENO, buffer, sizeof(buffer));

             /* 將字符串傳送給server端 */
             if(send | s, buffer, sizeof(buffer), 0) <0) {
                      perror("send");
                      exit(1);
              }
        }

}
endservent結束網絡服務數據的讀取
相關函數:getservent, getservbyname, getservbyport, setservent
表頭文件:#include <netdb.h>
函數定義:void endservent(void)
函數說明:endservent()用來關閉由getservent()所打開的文件
返回值   :無
範例:參getservent()
endprotoent結束網絡協議數據的讀取
相關函數:getprotoent, getprotobyname, getprotobynumber, setprotoent
表頭文件:#include <netdb.h>
函數定義:void endprotoent(void)
函數說明:endprotoent()用來關閉由getprotoent()所打開的文件
返回值   :無
範例       :參getprotoent()
gethostbyname由主機名稱取得網絡數據
相關函數:gethostbyaddr, sethostent
表頭文件:#include <netdb.h>
函數定義:struct hostent  *gethostbyname(const char *name)
函數說明:gethostbyname()會返回一個hostent結構,參數name可以爲一個主機名或IPv4/IPv6的IP地址。
struct  hostent
{
    char *h_name;           /*正式的主機名稱*/
    char **h_aliases;        /* 指向主機名稱的其他別名 */
    int h_addrtype;          /* 地址的型態, 通常是AF_INET */
    int h_length;             /*地址的長度*/
    char **h_addr_list;     /* 從域名服務器取得該主機的所有地址 */
};

返回值 :成功返回hostent結構指針,失敗則返回NULL指針, 錯誤原因存於h_errno變量中
錯誤代碼:
                HOST_NOT_FOUND                找不到指定的主機
                NO_ADDRESS                        該主機有名稱卻無IP地址
                NO_RECOVERY                      域名服務器有錯誤發生
                TRY_AGAIN                           請再調用一次
範例:
/*得用gethostbyname()的簡單反查IP程序*/           

 - #include <stdio.h>
   #include <netdb.h>
   #include <netinet/in.h>
   #include  <arpa/inet.h>

int main(int argc, char *argv[])
{
     struct hostent *hp;
     struct in_addr  in;
     struct sockaddr_in  local_addr;
     
     if(argc<2) return;
     if(!(hp=gethostbyname(argv[1]))) {
             fprintf(stderr, "Can't resolve host.\n");
             exit(1);
     }
     
     memcpy(&local_addr.sin_addr.s_addr, hp->h_addr, 4);
     in.s_addr= local_addr.sin_add.s_addr;
     printf("Domain Name:%s \n", argv[1]);
     printf("IP Address: %s\n", inet_ntoa(in));

}
gethostbyaddr由IP地址取得網絡數據
相關函數:gethostbyname
表頭文件:#inlcude <netdb.h>
函數定義:struct  hostent  *gethostbyaddr(const char *addr, int len, int type)
函數說明:gethostbyaddr()會返回一個hostent結構,參數addr可以爲IPv4或IPv6的IP地址,參數len爲參數addr的長度,參數type爲AF_INET。結構hostent定義請參gethostbyname()
返回值   :成功則返回hostent結構指針, 失敗則返回NULL指針,錯誤原因存於h_errno變量
錯誤代碼:HOST_NOT_FOUND    找不到指定的主機
               NO_ADDRESS             該主機有名稱卻無IP地址
               NO_RECOVERY           域名服務器有錯誤發生
               TRY_AGAIN               請再調用一次

範例:

 - w li

main(int argc, char *argv[])
{
    struct hostent  *host;
    if(argc<2) return;
    host = gethostbyaddr(argv[1], sizeof(argv[1]), AF_INET);
    if(host == (struct hostent * ) NULL) 
         herror("gethostbyaddr");
    else{
           printf("name :%s\n",  host->h_name);
           printf("type  :%s\n", host->h_addrtype);
           printf("addr  :%s\n", host->h_addr_list[0]);
    }
         
}
getprotobyname由網絡協議名稱取得協議數據
相關函數:getprotobynumber, getprotoent, setprotoent, endprotoent
表頭文件:#include <netdb.h>
函數定義:struct protoent *getprotobyname(const char *name)
函數說明:getprotobyname()會返回一個protoent結構,參數name爲欲查詢的網絡協議名稱。此函數會從/etc/protocols中查找各個符合條件的數據並由結構protoent返回。結構構protoent定義參getprotoent()
返回值   :成功返回protoent結構指針, 失敗或找不到符合的數據則返回NULL指針
範例:
/*取得icmp協議數據*/
 - #include <netdb.h>
main()
{ 
      struct protoent *protocol;
      protocol = getprotobyname("icmp");
      printf("protocol name :%s\n", protocol->p_name);
      printf("protocol number: %d\n", protocol->p_proto);
      printf("protocol alias : %s\n", protocol->p_aliases[0]);
}
getprotobynumber由網絡協議號取得協議數據
相關函數:getprotobyname, getprotoent, setprotoent, endprotoent
表頭文件:#include <netdb.h>
函數定義:struct protoent *getprotobynumber(int proto)
函 數說明:getprotobynumber()會返回一個protoent結構,參數proto爲欲查詢的網絡協議編號。此函數會從/etc /protocols中查找符合條件的數據並由結構protoent返回。 結構protoent定義請參getprotoent()
返回值   :成功則返回protoent結構指印,若有錯誤或找不到各個符合的數據則返回NULL指針

範例:
/*取得協議編號0到4的協議數據*/

 - #include <netdb.h>
 - 列表內容

main()
{
    int number;
    struct protoent *protocol;
    for(number=0; number<5; number++)
   {
       protocol = getprotobynumber(number);
       if(protocol == (struct protoent * ) NULL) continue;
       printf("%2d: %-10s: %-10s\n", protocol->p_proto, protocol->p_name, protocol->p_aliases[0]);
   }
}
getservbyname依名稱取得網絡服務的數據
相關函數:getservent, getservbyport, setservent, endservent
表頭文件:#include <netdb.h>
函數定義:struct servent *getservbyname(const char *name, const char *proto)
函 數說明:getservbyname()會返回一個servent結構, 參數name可以爲一個網絡服務的名稱,參數proto則爲該服務所使用的協議。此函數會從/etc/services中查找符合條件的數據並由結構 servent返回。結構servent的定義參getservent()
返回值:成功則返回servent結構指針, 失敗則返回NULL指針
範例:

 - #include <netdb.h>

main()
{
    struct servent  *s;
    s=getservbyname("telnet", "tcp");
    printf("%s %d/%s  \n", s->s_name, ntohs(s->s_port), s->s_proto);
}
getservbyport依port號碼取得網服務的數據
相關函數:getservent, getservbyname, setservent, endservent
表頭文件:#include <netdb.h>
函數定義:struct servent *getservbyport(int prot, const char *proto)
函 數說明:getservbyport()會返回一個servent結構,參數port可以爲一個port號碼,參數proto則爲該服務所使用的協議。此 函數會從/etc/services中查找符合條件的數據,並由結構servent返回。結構servent的定義請參考getservent()
附加說明:參數port必須先由htons()轉換
返回值  :成功則返回servent結構指針, 若有錯誤則返回NULL指針
範例:

 - #include <netdb.h>
main()
{
    struct servent *s;
    s=getservbyport(htons(23), "tcp");
    printf("%s %d/%s\n", s->s_name, ntohs(s->s_port), s->s_proto);
}
getservent取得主機網絡服務的數據
相關函數:getservbyname, getservbyport, setservent, endservent
表頭文件:#include <netdb.h>
函數定義:struct servent *getservent(void)
函數說明:getservent()會打開/etc/services, 然後讀取一行數據後由結構servent返回。之後再調用此函數則會繼續讀取下項數據,除非已到文件尾時返回NULL指針。
struct servent
{
     char  *s_name;     /*服務名稱*/
     char  **s_aliases;  /*別名列表*/
     int     s_port;       /*所使用的port號碼*/
     char   *s_proto;   /*使用的協議名稱*/
};

返回值  :成功則返回servent結構指針, 若有錯誤或讀到了文件尾則返回NULL指針
範例:
/*列出主機所有網絡服務的數據*/

 - #include <netdb.h>
main()
{    
     struct servent *s;
     while((s = getservent())
     {
           printf("%s %d/%s\n", s->s_name, ntobs(s->s_port), s->s_proto);
     }
     endservent();
}
getsockopt取得socket狀態
相關函數:setsockopt
表頭文件:#include <sys/types.h>
               #include <sys/socket.h>
函數定義:int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
函數說明:getsockopt()會將參數s所指定的socket狀態返回。
參數optname代表欲取得何種選項狀態
參數optval則指向欲保存結果的內存地址,
參數optlen則爲該空間的大小
參數level、optname請參setsockopt()
錯誤代碼:EBADF           參數s並非合法的socket處理代碼
               ENOTSOCK     參數s爲一文件描述詞,非socket
               ENOPROTOOPT 參數optname指定的選項不正確
               EFAULT            參數optval指針指向無法存取的內存空間
範例:
include <sys/types.h>
inlcude <sys/socket.h>

main()
{
    int  s, optval, optlen=sizeof(int);
    if((s=socket(AF_INET, SOCK_STREAM, 0)) <0)
             perror("socket");
    getsockopt(s, SOL_SOCKET, SO_TYPE, &optval, &optlen);
    printf("optval = %d\n", optval);
    close(s);
}
getprotoent取得網絡協議數據
相關函數:getprotobyname, getprotobynumber, setprotoent, endprotoent
表頭文件:#include <netdb.h>
函數定義:struct protoent *getprotoent(void)
函數說明:getprotoent()會打開/etc/protoclos,然後讀取一行數據後由結構protoent返回。之後再調用此函數則會繼續讀取下一項數據,除非已到文件尾時返回NULL指針
結構protoent定義
struct protoent
{
    char *p_name;    /*official protocol name*/
    char **p_aliases; /*alias list*/
    char p_proto;     /*protocol number*/
};


返回值  :成功則返回protoent結構指針,有錯或找不到符合的數據則返回NULL指針
範例:
/*取得所有協議數據*/

 - #include <netdb.h>
 - 列表內容

main()
{
    struct protoent *p;
    while(p=getprotoent())
     {
          printf("%s %s %d\n", p->p_name, p->aliases[0], p->p_proto);
     }   
     endprotoent();

 - }**重點內容**
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章