網路位元組序
1.tcp/ip協議規定,網路資料流應採用大端位元組序
0x12345678
小端儲存:78儲存在低位址
大端儲存:12儲存在低位址
網路位元組序和主機位元組序的轉換
#include uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
h表示host,n表示network,l(long)表示32位長整數,s(short)表示16位短整數。
如果主機是小端位元組序,這些函式將引數做相應的大小端轉換然後返回,如果主機是大端位元組序,這些函式不做轉
換,將引數原封不動地返回。
ip位址轉換函式192.168.56.101這就是乙個字串,要把這個字串轉換成32位的ip位址
#include int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
支援ipv4和ipv6
可重入函式
1.socket#include /* see notes */
#include int socket(int domain, int type, int protocol);
domain:
af_inet 這是大多數用來產生socket的協議,使用tcp或udp來傳輸,用ipv4的位址
af_inet6 與上面類似,不過是來用ipv6的位址
af_unix 本地協議,使用在unix和linux系統上,一般都是當客戶端和伺服器在同一臺及其上的時候使用
type:
sock_stream 這個協議是按照順序的、可靠的、資料完整的基於位元組流的連線。這是乙個使用最多的socket類
型,這個socket是使用tcp來進行傳輸。
sock_dgram 這個協議是無連線的、固定長度的傳輸呼叫。該協議是不可靠的,使用udp來進行它的連線。
sock_seqpacket 這個協議是雙線路的、可靠的連線,傳送固定長度的資料報進行傳輸。必須把這個包完整的
接受才能進行讀取。
sock_raw 這個socket型別提供單一的網路訪問,這個socket型別使用icmp公共協議。(ping、traceroute使
用該協議)
sock_rdm 這個型別是很少使用的,在大部分的作業系統上沒有實現,它是提供給資料鏈路層使用,不保證數
據包的順序
protocol:
0 預設協議
返回值:
成功返回乙個新的檔案描述符,失敗返回-1,設定errno
#include /* see notes */
#include int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:
socket檔案描述符
addr:
構造出ip位址加埠號
addrlen:
sizeof(addr)長度
返回值:
成功返回0,失敗返回-1, 設定errno
bind函式的第二個引數是由於歷史原因決定的,其實完全可以寫成void*型別,然後根據前16為類決定是哪一類的位址。
servaddr.sin_addr.s_addr = htonl(inaddr_any);//inaddr_any表示本機的任意的ip位址,可能有好幾個網絡卡。
servaddr.sin_port = htons(8000);
首先將整個結構體清零,然後設定位址型別為af_inet,網路位址為inaddr_any,這個巨集表示本地的任意ip位址,因為伺服器可能有多個網絡卡,每個網絡卡也可能繫結多個ip位址,這樣設定可以在所有的ip位址上監聽,直到與某個客戶端建立了連線時才確定下來到底用哪個ip位址,埠號為8000。
#include /* see notes */
#include int listen(int sockfd, int backlog);
sockfd:
socket檔案描述符
backlog:
排隊建立3次握手佇列和剛剛建立3次握手佇列的鏈結數和(核心維護的兩個佇列)
listen函式後面維護了兩個佇列,乙個是完成3次握手的佇列,乙個是未完成3次握手的佇列。,當呼叫accept函式時,就是從已連線的佇列中取出乙個已經完成3次握手的連線。
典型的伺服器程式可以同時服務於多個客戶端,當有客戶端發起連線時,伺服器呼叫的accept()返回並接受這個連線,如果有大量的客戶端發起連線而伺服器來不及處理,尚未accept的客戶端就處於連線等待狀態,listen()宣告sockfd處於監聽狀態,並且最多允許有backlog個客戶端處於連接待狀態,如果接收到更多的連線請求就忽略。listen()成功返回0,失敗返回-1。
#include /* see notes */
#include int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockdf:
socket檔案描述符
addr:
addrlen:
傳入傳出引數(值-結果),傳入sizeof(addr)大小,函式返回時返回真正接收到位址結構體的大小
返回值:
成功返回乙個新的socket檔案描述符,專門用於和客戶端通訊,失敗返回-1,設定errno
為什麼要產生新的socket呢原來的socket還要處理請求連線的。
三方握手完成後,伺服器呼叫accept()接受連線,如果伺服器呼叫accept()時還沒有客戶端的連線請求,就阻塞等待直到有客戶端連線上來。addr是乙個傳出引數,accept()返回時傳出客戶端的位址和埠號。addrlen引數是乙個傳入傳出引數(value-resultargument),傳入的是呼叫者提供的緩衝區addr的長度以避免緩衝區溢位問題,傳出的是客戶端位址結構體的實際長度(有可能沒有佔滿呼叫者提供的緩衝區)。如果給addr引數傳null,表示不關心客戶端的位址。
#include /* see notes */
#include int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockdf:
socket檔案描述符
addr:
傳入引數,指定伺服器端位址資訊,含ip位址和埠號
addrlen:
傳入引數,傳入sizeof(addr)大小
返回值:
成功返回0,失敗返回-1,設定errno
客戶端需要呼叫connect()連線伺服器,connect和bind的引數形式一致,區別在於bind的引數是自己的位址,而connect的引數是對方的位址。connect()成功回0,出錯返回-1。
server.c
#include #include #include #include #include #include #include #include #include #define err_exit(m) \
do \
while(0)
int main(void)
fputs(recvbuf, stdout);
write(conn, recvbuf, ret);
} close(listenfd);
close(conn);
return 0;
}
client.c
#include #include #include #include #include #include #include #include #include #define err_exit(m) \
do \
while(0)
int main(void)
; while(fgets(sendbuf, sizeof(sendbuf), stdin) != null)
close(sock);
return 0;
}
linux網路程式設計基礎api
socket系統呼叫,成功返回乙個socket檔案描述符,失敗返回 1並設定errno bind命名套接字,成功返回0,失敗返回 1並設定errno listen監聽socket,成功返回0,失敗返回 1並設定errno accept從listen監聽佇列中接受乙個連線,成功返回新的socket,失...
學習筆記 網路程式設計基礎API
linux網路程式設計基礎api與核心內tc ip協議族關係。1.socket位址api ip位址及埠對,代表tcp通訊中的一方,稱為socket位址。socket就像pipe一樣,代表的是乙個檔案描述符。可以用socket 來建立。參考 include see notes include int ...
網路程式設計 常用API
該類用於標識網路上的硬體資源,表示網際網路協議的ip位址 該類沒有構造方法,所以不能直接new出乙個物件,可以通過該類的靜態方法獲得inetaddress的物件 public class ipdemo url 統一資源定位符,表示internet上某一資源的位址 public class urlde...