什麼情況下,傳送端的send函式成功, 但傳送端抓不到對應的網路包?------深入理解send函式

stpeace發表於2017-07-20

       什麼情況狂下,傳送端的send函式成功, 但傳送端抓不到對應的網路包? 這是一個很有趣的問題。

       我們看下服務端程式:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>

int main()
{
	int sockSrv = socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in addrSrv;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_addr.s_addr = INADDR_ANY; 
	addrSrv.sin_port = htons(8765);

	bind(sockSrv, (const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));

	listen(sockSrv, 5);

	struct sockaddr_in addrClient;
	int len = sizeof(struct sockaddr_in);

	int sockConn = accept(sockSrv, (struct sockaddr *)&addrClient, (socklen_t*)&len);

    while(1)    
    {    
        getchar();    
        char szRecvBuf[1001] = {0};    
        int iRet = recv(sockConn, szRecvBuf, sizeof(szRecvBuf) - 1, 0);    
        printf("iRet is %d\n", iRet);     
    }

	getchar();
	close(sockConn);
	close(sockSrv);
	
	return 0;
}

        再看客戶端程式:

#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>


int main()
{
    int sockClient = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in addrSrv;
    addrSrv.sin_addr.s_addr = inet_addr("10.100.70.140");
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(8765);
    connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));

	#define N 2000
	char szSendBuf[N] = {0};
	for(unsigned int i = 0; i < N; i++) //×Ö·ûÊý×é×îºóÒ»¸ö×Ö·û²»ÒªÇóÊÇ¡®\0¡¯
	{
		szSendBuf[i] = 'a';	
	}

	int total = 0;
	while(1)
	{
		int iRet = send(sockClient, szSendBuf, sizeof(szSendBuf) , 0); 
		total += iRet;
		printf("iRet is %d, total send is %d\n", iRet, total);
		getchar();
	}

    close(sockClient);

    return 0;
}
       啟動服務端, 再啟動客戶端, 讓服務端一直髮發發, 發發發, 服務端不recv,  那麼過不了多久, 服務端的核心緩衝區就會滿了,  繼續發的話, 資料就會在客戶端的核心緩衝區中不斷堆積, 此時send函式還是會成功的(因為客戶端的傳送緩衝區沒有滿), 但是, 此時tcpdump是抓不到包的? 為什麼, 因為根本麼有傳送資料在網路卡上流動。

       這裡, 我們要再次說說send函式, send函式並沒有傳送資料的能力, send函式的作用僅僅是把應用程式的資料拷貝到傳送端的核心緩衝區中, 只要有足夠的空間, send函式就不會阻塞, 就會返回成功。 至於核心緩衝區中的資料是否傳送, 什麼時候傳送, 那是協議棧的事情,  跟send函式沒有半毛錢的關係。

       所以, send函式應該改名為copy_date_from_user_space_2_kerner_space.

       好的, 不多說。  有興趣的朋友, 可以親自試下上述實驗。





相關文章