//下邊這兩個結構定義在<sys/types.h>裡
//一般的地址結構,只能用於覆蓋(把其他地址轉換為此類型),且只能引用該地址的sa_family字段
struct sockaddr
{
unsigned char sa_len; //total length,整個結構體的長度,舊版本沒有
unsigned short sa_family; //地址族
char sa_data[14]; //地址的值
//TCP/IP使用的地址結構
struct sockaddr_in
{
unsigned char sin_len; //total length
short int sin_family; //地址族,一般為AF_INET(ipv4),ipv6為(AF_INET6)
unsigned short int sin_port; //端口號
struct in_addr sin_addr; //ip地址
char sin_zero[8]; //沒有使用(設置為0)
}
如果函數調用失敗,都返回-1,調用失敗會在全局變量error裡有相應的值
不涉及到讀取、發送的時候,調用正常都返回0
創建套接字
int socket(int family, int type, int protocol)
family: 協議或地址族,TCP/IP為PF_INET,(ipv6為PF_INET6),也可以使用AF_INET
type: 套接字類型
protocol:用來指定socket所使用的傳輸協議編號,通常設為0即可。
調用成功返回描述符
為套接字指明遠程端點的地址。為TCP時,connect使用三次握手建立連接;為UDP時,connect僅指明遠程端點,但是不向他發送任何數據
int connect(int sock, struct sockaddr \*serv_addr, int addrlen)
sock: 目的服務器的socket描述符
serv_addr:包含目的機器ip地址和端口號的指針
addrlen:sizeof(struct sockaddr)
調用成功返回0
linux下可以使用write(),將報文傳遞給目標主機
(int sock, char\* msg, int msglen, int flags);
flags:控制bit,指明是否接受帶外數據和是否預覽報文,一般為0
write(int sock, char* buf, int buflen)
buf:含有數據緩存的地址
buflen:buf中的字節數
這兩個函數調用成功時都返回傳送的字節數
從套接字中接收數據
nt recv(int sock, char\* buf, int len, int flags)
buf:存放數據的緩存地址
len:緩存的長度
flags:控制bit,指明是否接受帶外數據和是否預覽報文一般為0
read(int sock, char* buf, int buflen)
調用成功都返回讀取的字節數
從一個結構中獲取目的地址,然後發送報文
int sendto(int sock, char \*msg, int msglen, int flags, const struct sockaddr\* to, int\* tolen);
tolen:地址結構的字節長度
成功時,返回已發送的字節數
從套接字獲取下一個傳入報文,並記錄發送者的地址
int recvfrom(int sock, char\* buf, int buflen, int flags, struct sockaddr\* from, int\* fromlen)
```
fromlen:緩存的長度,返回時為發送者地址的大小。
成功調用時,返回報文中的字節數
### bind()
主要由服務器使用,指明本地ip地址和協議端口號
int bind(int sock, struct sockaddr *localaddr, int addrlen)
成功時返回0
### listen() -TCP
服務器調用,使套接字處於被動狀態(准備接受傳入請求)
int listen ( sock,queuelen)
queuelen:傳入鏈接請求的隊列大小(通常最大不超過5)
### accept() -TCP
bind->listen->accept,從隊列中取走下一個鏈接請求(或者一直在那裡等待下一個連接請求到來),為請求創建新套接字,並返回新套接字描述符。
int accept(int sock, struct sockaddr * addr, int* addrlen)
addrlen:初始指明為addr的大小,調用返回時為存儲在addr中的字節數
### close()
終止通信,刪除套接字,任何正在套接字上等待被讀取的數據都將被拋棄。
linux使用了引用計數機制,可以多個進程共享一個套接字。close每被調用一次,引用計數減1,引用計數為0時才釋放。
int close(int sock)
成功時返回0
### shutdown()
部分關閉連接
int shutdown(int sock,int direction )
direction:0,終止進一步輸入;1,終止進一步輸出;2,終止輸入和輸出
## 輔助函數
### 整數轉換
TCP/IP協議首部使用的二進制采用網絡字節順序(表示整數時,最高字節在前)
為了機器和網絡字節順序兼容,應當始終調用轉換函數
htons(host to network short)
ntohs
htonl
ntohl
### 地址轉換inet_addr
接受字符串(點分十進制),返回等價二進制表示的地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
```
接收ASCII字符串域名,返回hostent結構,定義在<netdb.h>
中
struct hostent
{
char* h_name, //正式主機名
char** h_aliases, //其他別名列表
int h_addrtype, //地址類型
int h_length, //地址長度
char** h_addr_list //一般主機可以有多個ip地址,h_addr_list用來
保存多個ip地址
}
#define h_addr h_addr_list[0] //為了與早期的版本兼容
成功則返回一個servent結構指針,發生差錯就返回空指針,結構定義在<netdb.h>
中
servent* getservbyname(char\* name, char\* proto)
struct servent
{
char* s_name; //正式服務名
char** s_aliases; //其他別名列表
int s_port; //該服務使用的端口
char *s_proto; //服務器所用的協議
};
```
成功就返回protoent結構指針,結構定義在<netdb.h>
中
struct protoent
{
char\* p_name; //協議正式名
char\*\* p_aliases; //協議的別名列表
int p_proto; //正式協議名
}
以字符串形式返回主機名
int gethostname(char\* name, namelen)
name:放置名字的字符數組的地址
需要已經建立鏈接
int getpeername(int sock, sockaddr\* remaddr, int\* addrlen)
remaddr:含有對端地址的sockaddr指針
addrlen:調用前為第二個參數的長度,調用後為遠程端點地址的實際長度
getsockopt()
setsockopt()
<sys/types.h> //primitive system data types(包含很多類型重定義,如pid_t、int8_t等)
<sys/socket.h> //與套接字相關的函數聲明和結構體定義,如socket()、bind()、connect()及struct sockaddr的定義等
//上邊兩個sock調用必須包含
<netinet/in.h> //某些結構體聲明、宏定義,如struct sockaddr_in、struct inaddr 、PROTO_ICMP、INADDR_ANY等
<sys/types.h> //primitive system data types(包含很多類型重定義,如pid_t、int8_t等)
<sys/socket.h> //與套接字相關的函數聲明和結構體定義,如socket()、bind()、connect()及struct sockaddr的定義等
<sys/ioctl.h> //I/O控制操作相關的函數聲明,如ioctl()
<stdlib.h> //某些結構體定義和宏定義,如EXIT_FAILURE、EXIT_SUCCESS等
<netdb.h> //某些結構體定義、宏定義和函數聲明,如struct hostent、struct servent、gethostbyname()、gethostbyaddr()、herror()等
<arpa/inet.h> //某些函數聲明,如inet_ntop()、inet_ntoa()等
<netinet/in.h> //某些結構體聲明、宏定義,如struct sockaddr_in、PROTO_ICMP、INADDR_ANY等