在linux下,一切都是檔案。檔案描述符是核心為了高效管理已經被開啟的檔案所創件的索引。它是乙個非負整數int fd,用於指代被開啟的檔案。所有執行io操作的系統呼叫都是通過檔案描述符來完成的。
open、creat等低階io函式返回檔案描述符。不採用緩衝區去寫,依賴作業系統功能對檔案讀寫,不設檔案結構體指標,只能讀寫二進位制檔案。
區別於fopen等高階io函式。fopen等高階io函式返回的是乙個指向檔案file型別的指標,它們採用緩衝檔案系統。在記憶體為每個檔案開闢乙個快取區,當執行讀操作,從磁碟檔案將資料讀入記憶體緩衝區,裝滿後從記憶體緩衝區依次讀取資料。寫操作同理。記憶體緩衝區的大小影響著實際操作外存的次數,緩衝區越大,操作外存的次數越少,執行速度快,效率高。緩衝區大小由機器而定。
為了執行網路io,會呼叫socket建立套接字。socket會返回套接字描述符。套接字描述符與檔案描述符類似,簡稱sockfd。sockfd也指向乙個套接字(在核心中也是乙個檔案)。呼叫該描述符,可以對套接字進行網路io。
int fd:檔案描述符或套接字描述符。在網路io中,是套接字描述符sockfd。用於指向核心中的某個套接字。
void *buf:乙個空指標,一般傳入乙個指向char陣列的指標,用於快取讀出來的資訊。
size_t nbytes:請求讀位元組數。讀出的資料儲存到buf上,同時檔案讀寫位置後移動count。
讀正確,則返回讀出的位元組數,網路io中,可能由於網路緩衝機制,小於count。
讀失敗,則返回-1;
讀到檔案末尾,則返回0。
該值是函式內的錯誤標誌位。如果讀取失敗,函式呼叫返回-1,且置erron為錯誤。如果讀取失敗,但是不是因為讀取出錯,而是因為遇到中斷,則函式返回-1,但是erron置為 eintr。通過檢查erron,直到讀寫錯在**。
//建立套接字,返回套接字描述符
int client_fd =
socket
(af_inet, sock_stream,0)
;//……
char msg[
1024];
//讀出的資訊儲存在msg上
int rbytes =-1
;if((rbytes =
read
(client_fd, msg,
sizeof
(msg)-1
))>0)
else
printf
("read error=%d(%s)!!!\n"
, errno,
strerror
(errno)
);
#include
ssize_t write
(int fd,
const
void
*buf, size_t nbytes)
int fd:檔案描述符或套接字描述符。在網路io中,是套接字描述符sockfd。用於指向核心中的某個套接字。
const void *buf :乙個const空指標,一般傳入乙個指向char陣列的指標,該陣列儲存我們要寫入的資料。const意味著函式只能讀而不能改變這個指標指向的記憶體單元。
size_t nbytes:請求寫位元組數。把buf上面的nbytes個位元組寫到指定的套接字緩衝區。每次寫之前,會將檔案讀寫位置移動到檔案的當前結尾處,寫完後,再將檔案讀寫位置雜恩公加實際寫的位元組數。
讀正確,則返回實際寫的位元組數。可能小於nbytes。
讀失敗,則返回-1;
該值是函式內的錯誤標誌位。如果讀取失敗,函式呼叫返回-1,且置erron為錯誤。如果讀取失敗,但是不是因為讀取出錯,而是因為遇到中斷,則函式返回-1,但是erron置為 eintr。通過檢查erron,直到讀寫錯在**。
//……
//監聽到連線套接字,具體見accept
int client_fd =
accept
(listen_fd,
null
,null);
//……
const
char
*msg=
"hello!"
;//寫入資料if(
write
(client_fd, msg,
strlen
(msg))!=
strlen
(msg)
)printf
("send msg to client error!!!\n");
close
(client_fd)
;
#include
int snprintf (
char
*str, size_t size,
const
char
*format,..
.)
str:目標字串
size:拷貝位元組數(bytes),寫入的最大位元組數
format:格式化字串
…:可變引數
將可變引數(…)按照format格式化成字串,並將字串複製到str中,size為要寫入的字元的最大數目,超過size會被截斷。
如果格式化後的字串長度小於size,則把字串全部複製到str中,並給其後新增乙個』\0』,返回欲寫入的字串長度。
如果大於等於size,超過部分會被截斷。只將其中的size-1複製到str中,並在最後新增』\0』,返回欲寫入的字串長度。
#include
intmain()
string:
123456789
返回值為:9
string:
012345678
返回值為:10
網路io中的read函式和write函式和通常的檔案io有區別。在網路io中使用這兩個函式,可能返回的值小於請求的位元組數。這是因為可能在核心中用於套接字的緩衝區可能已經到達了極限。
此時需要再次呼叫read或write,從而輸入或輸出剩餘位元組。因此考慮使用包裹函式減少這些情況。
#include
ssize_t readn
(int fd,
void
*buf, size_t nbytes)
;
ssize_t readn
(int fd,
void
*buf, size_t nbytes)
//如果等於0,說明讀到了結尾
else
if(nread ==0)
break
;//更新剩餘位元組數
nleft -
= nread;
//更新buf陣列的指標位置,繼續迴圈讀取
ptr +
= nread;
}//返回讀取的位元組數,一般為nbytes。
return
(nbytes - nleft)
;}
#include
ssize_t writen
(int fd,
void
*buf, size_t nbytes)
;
ssize_t writen
(int fd,
const
void
*buf, size_t nbytes)
nleft -
= nwritten;
ptr +
= nwritten;
}return
(nbytes)
;//返回寫入了多少位元組
}
網路程式設計常用I O函式
read write readv writev 對資料進行整合傳輪及傳送的函式。也就是說,通過writev 函式可以將分散儲存在多個緩衝中的資料一併傳送,通過readv函式可以由多個緩衝分別接收。因此,適當使用這2個函式可以減少i o函式的呼叫次數。下面先介紹writev 函式。include ss...
常用檔案IO函式
include include include int open const char pathname,int flags int open const char pathname,int flags,mode t mode 功能 開啟檔案,如果檔案不存在則可以選擇建立。引數 pathname 檔...
網路程式設計的4種IO模型
select fd zero初始化 fd set將socket加進去 select輪詢 當socket的事件發生時,fd set裡面有相關的socket,如果沒有socket有事件發生,select返回0 fd isset檢測,socket是否還在fd set裡,是的話,表示這個socket有事件發...