Linux網(wǎng)絡(luò)編程--4. 完整的讀寫(xiě)函數(shù)
發(fā)布時(shí)間:2008-09-17 閱讀數(shù): 次 來(lái)源:網(wǎng)樂(lè)原科技
一旦我們建立了連接,我們的下一步就是進(jìn)行通信了.在Linux下面把我們前面建立的通道 看成是文件描述符,這樣服務(wù)器端和客戶端進(jìn)行通信時(shí)候,只要往文件描述符里面讀寫(xiě)東西了. 就象我們往文件讀寫(xiě)一樣.
4.1 寫(xiě)函數(shù)write
ssize_t write(int fd,const void *buf,size_t nbytes)
write函數(shù)將buf中的nbytes字節(jié)內(nèi)容寫(xiě)入文件描述符fd.成功時(shí)返回寫(xiě)的字節(jié)數(shù).失敗時(shí)返回-1. 并設(shè)置errno變量. 在網(wǎng)絡(luò)程序中,當(dāng)我們向套接字文件描述符寫(xiě)時(shí)有倆種可能.
1)write的返回值大于0,表示寫(xiě)了部分或者是全部的數(shù)據(jù).
2)返回的值小于0,此時(shí)出現(xiàn)了錯(cuò)誤.我們要根據(jù)錯(cuò)誤類(lèi)型來(lái)處理.
如果錯(cuò)誤為EINTR表示在寫(xiě)的時(shí)候出現(xiàn)了中斷錯(cuò)誤.
如果為EPIPE表示網(wǎng)絡(luò)連接出現(xiàn)了問(wèn)題(對(duì)方已經(jīng)關(guān)閉了連接).
為了處理以上的情況,我們自己編寫(xiě)一個(gè)寫(xiě)函數(shù)來(lái)處理這幾種情況.
int my_write(int fd,void *buffer,int length)
{
int bytes_left;
int written_bytes;
char *ptr;
ptr=buffer;
bytes_left=length;
while(bytes_left>0)
{
/* 開(kāi)始寫(xiě)*/
written_bytes=write(fd,ptr,bytes_left);
if(written_bytes<=0) /* 出錯(cuò)了*/
{
if(errno==EINTR) /* 中斷錯(cuò)誤 我們繼續(xù)寫(xiě)*/
written_bytes=0;
else /* 其他錯(cuò)誤 沒(méi)有辦法,只好撤退了*/
return(-1);
}
bytes_left-=written_bytes;
ptr+=written_bytes; /* 從剩下的地方繼續(xù)寫(xiě) */
}
return(0);
}
4.2 讀函數(shù)read
ssize_t read(int fd,void *buf,size_t nbyte) read函數(shù)是負(fù)責(zé)從fd中讀取內(nèi)容.當(dāng)讀成功時(shí),read返回實(shí)際所讀的字節(jié)數(shù),如果返回的值是0 表示已經(jīng)讀到文件的結(jié)束了,小于0表示出現(xiàn)了錯(cuò)誤.如果錯(cuò)誤為EINTR說(shuō)明讀是由中斷引起的, 如果是ECONNREST表示網(wǎng)絡(luò)連接出了問(wèn)題. 和上面一樣,我們也寫(xiě)一個(gè)自己的讀函數(shù).
int my_read(int fd,void *buffer,int length)
{
int bytes_left;
int bytes_read;
char *ptr;
bytes_left=length;
while(bytes_left>0)
{
bytes_read=read(fd,ptr,bytes_read);
if(bytes_read<0)
{
if(errno==EINTR)
bytes_read=0;
else
return(-1);
}
else if(bytes_read==0)
break;
bytes_left-=bytes_read;
ptr+=bytes_read;
}
return(length-bytes_left);
}
4.3 數(shù)據(jù)的傳遞
有了上面的兩個(gè)函數(shù),我們就可以向客戶端或者是服務(wù)端傳遞數(shù)據(jù)了.比如我們要傳遞一個(gè)結(jié)構(gòu).可以使用如下方式
/* 客戶端向服務(wù)端寫(xiě) */
struct my_struct my_struct_client;
write(fd,(void *)&my_struct_client,sizeof(struct my_struct);
/* 服務(wù)端的讀*/
char buffer[sizeof(struct my_struct)];
struct *my_struct_server;
read(fd,(void *)buffer,sizeof(struct my_struct));
my_struct_server=(struct my_struct *)buffer;
在網(wǎng)絡(luò)上傳遞數(shù)據(jù)時(shí)我們一般都是把數(shù)據(jù)轉(zhuǎn)化為char類(lèi)型的數(shù)據(jù)傳遞.接收的時(shí)候也是一樣的 注意的是我們沒(méi)有必要在網(wǎng)絡(luò)上傳遞指針(因?yàn)閭鬟f指針是沒(méi)有任何意義的,我們必須傳遞指針?biāo)赶虻膬?nèi)容)