頭文件
#include
socket()
//創建網絡端點,返回socket文件描述符,失敗返回-1設errnoint socket(int domain, int type, int protocol);
domain?:協議族(protocol family)(網絡通訊(IP)還是本地通訊(xxx.socket))
- AF_LOCAL本地通訊/AF_UNIX/
- AF_INET用于實現給予ipv4網絡協議的網絡協議
- AF_INET6用于實現給予ipv6網絡協議的網絡協議
- AF_IPXIPX - Novell protocols
- AF_NETLINKKernel user interface device
- AF_X25?ITU-T X.25 / ISO-8208 protocol
- AF_AX25?Amateur radio AX.25 protocol
- AF_ATMPVC?Access to raw ATM PVCs
- AF_APPLETALK?Appletalk
- AF_PACKET?Low level packet interface
type?:協議(TCP還是UDP還是其他的)
- SOCK_STREAM?//流式套接字, 實現包括但不限于TCP協議,which is有序,可靠雙向面向連接的字節流通信方式
- SOCK_DGRAM?//數據報套接字, 實現包括但不限于UDP協議, which is不可靠,無連接的數據報通信方式
- SOCK_SEQPACKET
- SOCK_RAW?//原始套接字,可以編寫自己的傳輸層協議
- SOCK_RDM
- SOCK_PACKET
can be bitwised:
- SOCK_NONBLOCK?//將O_NONBLOCK文件狀態標識符放在新打開的文件描述符上,將打開的文件設為非阻塞。也可以通過fcntl()達到同樣的目的
- SOCK_CLOEXEC?//將 close-on-exec (FD_CLOEXEC)文件標識符放在新打開的文件描述符上。參見open()
protocol: 特殊協議, 一般給0
Note:
雖然socket返回的sockfd就是一個文件描述符,但不是所有的以文件描述符為參數的函數都可以操作sockfd,比如,和管道文件一樣,sockfd同樣不能被lseek()操作,下面是一些以文件描述符為參數的函數在操作sockfd時的行為(取自《UNIX環境高級編程》P476)
close() //釋放sockfdDup(),dup2() //和一般的文件描述符一樣復制fchdir() //失敗fchmod() //未指定fchown() //由實現定義fcntl() //支持一些命令,eg:F_DUFD,F_DUPFD_CLOEXEC,F_GETFD,F_GETFL,F_GETOWN,F_SETFD,F_SETFL,F_SETOWNFdatasync()和fsync() //fstat() //由實現定義ftruncate() //未指定ioctl() //支持部分指令,依賴于底層驅動lseek() //由實現定義,失敗會設errno為ESPIPEmmap() //未指定poll() //正常工作read()/readv() //與沒有flag的recv()等價select() //正常工作write()/writev() //與沒有flag的write()等價
getsockopt()/setsockopt()
//獲得sockfd指向的socket的屬性int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);//設置sockfd指向的socket的屬性,成功返回0,失敗返回-1設errno。int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
level?:選項級別
- SOL_SOCKET:指定設置屬性在socket API層次,即通用socket選項
- IPPROTO_IP:IP選項。
- IPPROTO_TCP:TIP選項。
optname:選項名
- SO_BROADCAST:廣播
optval:存放選項值的緩沖區地址
optlen:緩沖區長度
準備通信地址:
struct sockaddr{ //主要用于函數的形參類型, 很少定義結構體變量使用, 叫做通用的通信地址類型//$man bind sa_family_t sa_family; char sa_data[14];}struct sockaddr_un{ //準備本地通信的通信地址 //$man un.h sa_family_t sun_family;//協議族,就是socket()的domain的AF_LOCAL char sun_path[];//文件的路徑}struct sockaddr_in{ //準備網絡通信的通信地址 //$man in.h sa_family_t sin_family; //協議族, 就是socket()的domain的AF_INET in_port_t sin_port; //端口號 struct in_addr sin_addr; //IP地址}struct in_addr{ in_addr_t s_addr; //整數類型的IP地址}
htonl()/htons()/ntohl()/ntohs()
//主機和網絡字節序轉換uint32_t htonl(uint32_t hostlong);converts the unsigned integer hostlong from host byte order to network byte order.uint16_t htons(uint16_t hostshort);converts the unsigned short integer hostshort from host byte order to network byte order.uint32_t ntohl(uint32_t netlong); converts the unsigned integer netlong from network byte order to host byte order.uint16_t ntohs(uint16_t netshort); converts the unsigned short integer netshort from network byte order to host byte
inet_aton()/inet_addr()/inet_lnaof()/inet_netof()/inet_network()/inet_ntoa()/inet_makeaddr()
//IP地址格式轉換,返回對應格式的IP地址int · inet_aton(const char *cp, struct in_addr *inp);in_addr_t inet_addr(const char *cp); //將字符串形式的IP地址轉換為整數類型in_addr_t inet_lnaof(struct in_addr in);in_addr_t inet_netof(struct in_addr in);in_addr_t inet_network(const char *cp);char* inet_ntoa(struct in_addr in); //將結構體類型的IP地址轉換為字符串類型struct in_addr inet_makeaddr(int net, int host);
bind()
//把通信端口(可能還有地址)和socket文件描述符綁定,用在服務器端,成功返回0,失敗返回-1設errnoint bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd: socket文件的fd(returned by socket())
addr: 需要強制類型轉換成socketaddr_un或soketaddr_in, 參見上
addrlen: 通信地址的大小, 使用sizeof();
Note:一個網卡一個MAC和一個ip地址,如果將地址置為INADDR_ANY(就是0),那么表示從所有的網卡接收消息,如果希望只接收特定網卡的消息,就需要將其ip地址與socket綁定
connect():
//初始化一個socket的連接,用在客戶端,成功返回0,失敗返回-1設errnoint connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd: socket文件的fd(returned by socket())
addr: 需要強制類型轉換成socketaddr_un或soketaddr_in, 參見上
addrlen: 通信地址的大小, 使用sizeof();
shutdown()
//將一個socket設為不活動狀態。成功返回0,失敗返回-1設errnoint shutdown(int sockfd, int how);
sockfd:socket文件的文件描述符
how:shutdown的方式
- SHUT_RD關閉socket的讀端
- SHUT_WR關閉socket的寫端
- SHUT_RDWR關閉socket的讀端和寫端
當我們close(sockfd)的時候,其實是使引用該文件的文件描述符個數-1,只有當所有引用該文件的文件描述符都被close()時,這個文件才會真正被釋放,比如我們在close一個文件描述符之前調用了dup()來復制這個文件描述符,那么這個文件描述符指向的文件表其實還是存在的。當這里的文件描述符指的是socketfd時也是同樣的道理。而shutdown()可以直接將該sockfd指向的socket設為不活動狀態,那么其他指向該socket的fd也會直接受到影響
網絡信息檢索函數
//獲取主機名gethostname();//獲取與socket相連的遠程協議的地址getscokname()//獲得本地socket協議地址getsockname()//根據主機名獲得主機信息gethostbyname()//根據主機地址取主機信息gethostbyaddr()//根據協議名取得主機協議信息getprotobyname()//根據協議號取得主機協議信息getprotobynumber()//根據服務名取得相關服務信息getservbyname()//根據端口號取得相關服務信息getservbyport()
評論