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(); - }**重點內容**
linux c 網絡編程, 常用網絡函數,範例
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.