recv或者recvfrom

來源:互聯網
上載者:User

recv和recvfrom都是用來接受來自的網路的資料。來看看它們的原型:

 

int recv(
  SOCKET
{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">s
,      
  char FAR *{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">buf
, 
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">len
,       
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">flags      

);

int recvfrom(
  SOCKET
{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">s
,                  
  char FAR* {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">buf
,             
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">len
,                   
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">flags
,                 
  struct sockaddr FAR *{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">from
, 
  int FAR *{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">fromlen           

);

 

這是在windows下面的定義。在linux下面的定義只是將SOCKET改成int,那麼在linux下面的原型是這樣:

 

int recv(
  int
{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">s
,      
  char FAR *{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">buf
, 
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">len
,       
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">flags      

);

 

int recvfrom(
  int
{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">s
,                  
  char FAR* {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">buf
,             
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">len
,                   
  int {
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">flags
,                 
  struct sockaddr FAR *{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">from
, 
  int FAR *{
function onclick()
{
function onclick()
{
showTip(this)
}
}
}">fromlen           

);

 

 

其實要是看看windows中SOCKET的定義,就知道它們幾乎是完全相同了,為什麼是幾乎?因為還是有點小區別,linux下面是int類型,而windows下面是unsigned int。下面就是windows中SOCKET的定義:

typedef UINT_PTR        SOCKET;

typedef unsigned int UINT_PTR, *PUINT_PTR;

 

插一句,在linux下面這裡的int s, 其實代表的是檔案描述符。在linux中所有的裝置,如磁碟,光碟機,U盤甚至我們這裡的討論的網路也都被看作是檔案。

 

我們看看這兩個函數在功用上的共同點和不同點:

 

共同點:

1. 都是用來接受來自網路的資料

 

2. 都可以 接受連線導向的流式通訊端的 和 接受不需連線的資料通訊端 的資料

 

3. 在成功接受到資料後,傳回值都是實際接受的位元組數; 通訊端關閉時,返回都為0; 接受出錯時,windows下面都返回SOCKET_ERROR , linux下面都返回-1, 其實你要是感興趣可以查看SOCKET_ERROR 定義,它的值也是-1;

關於這裡的“通訊端關閉”需要注意,2個函數在用在流式通訊端和資料通訊端時,通訊端表示的含義不一樣,前者表示用戶端通訊端,而後者表示的是自己的通訊端。

 

4. 如果通訊端為阻塞的,在系統緩衝中沒有資料的情況下,都將阻塞;如果通訊端為非阻塞的,在系統緩衝中沒有資料的情況下,都將立即返回,傳回值在linux下為-1, errno被設定為EWOULDBLOCK,在windows下面返回SOCKET_ERROR, 通過WSAGetLastError返回WSAEWOULDBLOCK.

 

5. 如果用在流式通訊端,則2者的操作是:將已在核心緩衝區的資料拷貝到應用程式自己的緩衝區,拷貝的最大的長度為調用函數時傳入的緩衝區的長度,注意這裡的長度不一定等於實際緩衝區的長度,可以小於緩衝區的長度,但是絕對不能大於,為什麼不能大於,也許你比我更清楚。例如下面這段代碼:

char szRecvBuf[1024] = { 0 };

recv( sockServer, szRecvBuf, 256, 0 );

這裡雖然定義的緩衝區的長度為1024但是接受的時候只用其中的256. 如果核心緩衝區當時有10個位元組,那麼這次調用立刻返回,szRecvBuf被填充了10位元組,傳回值是10。 如果核心緩衝區有1500個位元組,那麼szRecvBuf將被填充256個位元組,傳回值就是256.                               

如果是資料通訊端,在核心緩衝區中的資料小於要求長度(這裡是256)的情況下,和流式通訊端結果一樣。但是大於的情況就不一樣了,首先將填充256到szRecvBuf中,並且產生一個WASEMSGSIZE的錯誤,並且剩下的部分被丟棄。假如核心緩衝區的資料為1000位元組,那麼前面的256被填充到szRecvBuf中,後面的1000-256將被丟棄。

recvfrom的執行效果也是同樣的。

上面的結論是結合msdn和實際的測試得出的。

recvfrom的實際效果也是這樣。

 

不同點:

1. 函數參數不一樣

 

未完待續...

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.