一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

socket編程中write、read和send、recv之間的區(qū)別

 gljin_cn 2014-03-22
  一旦,我們建立好了tcp連接之后,我們就可以把得到的fd當(dāng)作文件描述符來(lái)使用。
由此網(wǎng)絡(luò)程序里最基本的函數(shù)就是read和write函數(shù)了。
ssize_t write(int fd, const void*buf,size_t nbytes);
write函數(shù)將buf中的nbytes字節(jié)內(nèi)容寫入文件描述符fd.成功時(shí)返回寫的字節(jié)數(shù).失敗時(shí)返回-1. 并設(shè)置errno變量. 在網(wǎng)絡(luò)程序中,當(dāng)我們向套接字文件描述符寫時(shí)有兩可能.
1)write的返回值大于0,表示寫了部分或者是全部的數(shù)據(jù). 這樣我們用一個(gè)while循環(huán)來(lái)不停的寫入,但是循環(huán)過(guò)程中的buf參數(shù)和nbyte參數(shù)得由我們來(lái)更新。也就是說(shuō),網(wǎng)絡(luò)寫函數(shù)是不負(fù)責(zé)將全部數(shù)據(jù)寫完之后在返回的。
2)返回的值小于0,此時(shí)出現(xiàn)了錯(cuò)誤.我們要根據(jù)錯(cuò)誤類型來(lái)處理.
如果錯(cuò)誤為EINTR表示在寫的時(shí)候出現(xiàn)了中斷錯(cuò)誤.
如果為EPIPE表示網(wǎng)絡(luò)連接出現(xiàn)了問(wèn)題(對(duì)方已經(jīng)關(guān)閉了連接).
為了處理以上的情況,我們自己編寫一個(gè)寫函數(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)
{
        
         written_bytes=write(fd,ptr,bytes_left);
         if(written_bytes<=0)
              
                 if(errno==EINTR)
                         written_bytes=0;
                 else             
                         return(-1);
         }
         bytes_left-=written_bytes;
         ptr+=written_bytes;     
}
return(0);
}

讀函數(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)題. 和上面一樣,我們也寫一個(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);
}

數(shù)據(jù)的傳遞
有了上面的兩個(gè)函數(shù),我們就可以向客戶端或者是服務(wù)端傳遞數(shù)據(jù)了.比如我們要傳遞一個(gè)結(jié)構(gòu).可以使用如下方式



struct my_struct my_struct_client;
write(fd,(void *)&my_struct_client,sizeof(struct my_struct);


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類型的數(shù)據(jù)傳遞.接收的時(shí)候也是一樣的注意的是我們沒有必要在網(wǎng)絡(luò)上傳遞指針(因?yàn)閭鬟f指針是沒有任何意義的,我們必須傳遞指針?biāo)赶虻膬?nèi)容)


6.1 recv和send
recv和send函數(shù)提供了和read和write差不多的功能.不過(guò)它們提供了第四個(gè)參數(shù)來(lái)控制讀寫操作.

int recv(int sockfd,void *buf,int len,int flags)
int send(int sockfd,void *buf,int len,int flags)

前面的三個(gè)參數(shù)和read,write一樣,第四個(gè)參數(shù)可以是0或者是以下的組合
_______________________________________________________________
| MSG_DONTROUTE | 不查找表 |
| MSG_OOB | 接受或者發(fā)送帶外數(shù)據(jù) |
| MSG_PEEK | 查看數(shù)據(jù),并不從系統(tǒng)緩沖區(qū)移走數(shù)據(jù) |
| MSG_WAITALL | 等待所有數(shù)據(jù) |
|--------------------------------------------------------------|

MSG_DONTROUTE:是send函數(shù)使用的標(biāo)志.這個(gè)標(biāo)志告訴IP.目的主機(jī)在本地網(wǎng)絡(luò)上面,沒有必要查找表.這個(gè)標(biāo)志一般用網(wǎng)絡(luò)診斷和路由程序里面.
MSG_OOB:表示可以接收和發(fā)送帶外的數(shù)據(jù).關(guān)于帶外數(shù)據(jù)我們以后會(huì)解釋的.

MSG_PEEK:是recv函數(shù)的使用標(biāo)志,表示只是從系統(tǒng)緩沖區(qū)中讀取內(nèi)容,而不清除系統(tǒng)緩沖區(qū)的內(nèi)容.這樣下次讀的時(shí)候,仍然是一樣的內(nèi)容.一般在有多個(gè)進(jìn)程讀寫數(shù)據(jù)時(shí)可以使用這個(gè)標(biāo)志.

MSG_WAITALL是recv函數(shù)的使用標(biāo)志,表示等到所有的信息到達(dá)時(shí)才返回.使用這個(gè)標(biāo)志的時(shí)候recv回一直阻塞,直到指定的條件滿足,或者是發(fā)生了錯(cuò)誤. 1)當(dāng)讀到了指定的字節(jié)時(shí),函數(shù)正常返回.返回值等于len 2)當(dāng)讀到了文件的結(jié)尾時(shí),函數(shù)正常返回.返回值小于len 3)當(dāng)操作發(fā)生錯(cuò)誤時(shí),返回-1,且設(shè)置錯(cuò)誤為相應(yīng)的錯(cuò)誤號(hào)(errno)


MSG_NOSIGNAL is a flag used by send() in some implementations of the Berkeley sockets API.

This flag requests that the implementation does not to send a SIGPIPE signal on errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned as normal.

Though it is in some Berkely sockets APIs (notably Linux) it does not exist in what some refer to as the reference implementation, FreeBSD, which instead uses a socket option SO_NOSIGPIPE?. 對(duì)于服務(wù)器端,我們可以使用這個(gè)標(biāo)志。目的是不讓其發(fā)送SIG_PIPE信號(hào),導(dǎo)致程序退出。

如果flags為0,則和read,write一樣的操作.還有其它的幾個(gè)選項(xiàng),不過(guò)我們實(shí)際上用的很少,可以查看 Linux Programmer's Manual得到詳細(xì)解釋

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    偷拍洗澡一区二区三区| 亚洲男人的天堂色偷偷| 国产欧美日本在线播放| 国产伦精品一区二区三区精品视频| 日本黄色美女日本黄色| 中文字幕久热精品视频在线| 麻豆在线观看一区二区| 日本一级特黄大片国产| 色婷婷日本视频在线观看| 日本精品中文字幕人妻| 亚洲欧美中文日韩综合| 亚洲av首页免费在线观看| 久久99夜色精品噜噜亚洲av | 久久中文字人妻熟女小妇| 91日韩在线观看你懂的| 国产又色又爽又黄的精品视频| 日本熟妇熟女久久综合| 日韩午夜老司机免费视频| 欧美日韩精品久久亚洲区熟妇人| 九九九热视频免费观看| 日韩精品日韩激情日韩综合| 青青久久亚洲婷婷中文网| 色哟哟精品一区二区三区| 中文字幕一二区在线观看| 内射精品欧美一区二区三区久久久 | 精品精品国产欧美在线| 免费性欧美重口味黄色| 日韩中文字幕狠狠人妻| 91午夜少妇极品福利| 好吊妞在线免费观看视频| 天堂网中文字幕在线视频| 午夜福利在线观看免费| 久久re6热在线视频| 日韩国产传媒在线精品| 国产成人精品午夜福利| 国产91色综合久久高清| 国产精品成人一区二区在线| 国产精品视频一区二区秋霞| 欧美美女视频在线免费看| 国产一区欧美午夜福利| 中文字幕有码视频熟女|