1 案例背景
在學習TCP-IP協議詳解卷一時,讀到介紹TCP協議的部分,發現TCP的首部是沒有報文總長度字段的,而在UDP中是有的,對這個問題的思考引出了兩者之間的區別。
2 案例分析
TCP報文的格式:
TCP首部的格式:
UDP報文的格式:
UDP首部的格式:
針對首部公共部分的對比,很明顯的一個區別是UDP首部是有數據報總長度字段的,而TCP首部是沒有數據報總長度字段的,這個原因的解釋在TCP-IP詳解卷一答案中的解釋是TCP首部有選項字段而UDP首部大小是固定的,而網上的查詢結果有一種是因為模式的不同。
我比較贊同的是,TCP是面向連接的流模式,而UDP是不連接的數據報模式。
3 實驗
實驗一:
TCP客戶端循環發送數據到服務器,主循環部分分三次調用send或者sendto,分別發送111,222,333;而服務器是睡眠十秒,然后調用recv或者recvfrom接收數據。注意,只接收一次。
客戶端發送部分(其中的sendto可用send代替):
while(1)
{
memset(achBuf,0,1024);
memcpy(achBuf,"111",3);
buflen = strlen(achBuf);
ret = sendto(nSockFd,achBuf,buflen,0,(struct sockaddr*)&ServAddr,sizeof(ServAddr));
memset(achBuf,0,1024);
memcpy(achBuf,"222",3);
buflen = strlen(achBuf);
ret = sendto(nSockFd,achBuf,buflen,0,(struct sockaddr*)&ServAddr,sizeof(ServAddr));
memset(achBuf,0,1024);
memcpy(achBuf,"333",3);
buflen = strlen(achBuf);
ret = sendto(nSockFd,achBuf,buflen,0,(struct sockaddr*)&ServAddr,sizeof(ServAddr));
}
服務器接收部分(其中的recv可用recvfrom代替):
sleep(10);
recv(conn,buf,1024,0);
printf("conn = %s\n",buf);
四種不同的發送接收組合,均是以下結果:
實驗二:
UDP客戶端循環發送數據到服務器,分三次調用sendto,分別發送了111,222,333;服務器睡眠十秒,然后調用recvfrom循環接收數據。為了表示是第幾次接收到的數據,首先打印接收序號。
客戶端發送部分:
nNum = sendto(nSockFd,"111\n", 12, 0, (struct sockaddr *)&MCAddr,sizeof(MCAddr));
printf("nNum = %d\n",nNum);
nNum = sendto(nSockFd,"222\n", 12, 0, (struct sockaddr *)&MCAddr,sizeof(MCAddr));
printf("nNum = %d\n",nNum);
nNum = sendto(nSockFd,"333\n", 12, 0, (struct sockaddr *)&MCAddr,sizeof(MCAddr));
printf("nNum = %d\n",nNum);
服務器接收部分:
while(1)
{
sleep(10);
memset(achBuf,0,MAXBUFLEN);
nNum = recvfrom(nServFd,achBuf,MAXBUFLEN,0,(struct sockaddr *)&CliAddr, &dwCliAddrLen);
if(nNum < 0)
{
printf("recverror\n");
break;
}
printf("%d\n",i);i++;
printf("%s\n",achBuf);
}
結果如下圖:
4 總結
由實驗結果可以知道,讀取數據的方式和調用的函數沒有關系,而和套接字類型有關。而TCP接收數據時不是一次只讀取一個數據報,而是根據buf的大小和緩沖區數據的大小中的較小值來讀取數據的,可以一次性讀取多個數據報;而UDP是按照接收到的數據次序,一次只讀取一個數據報。
現在可以大概的推敲出流模式和數據報模式的區別,接收和發送數據方式的不同。流模式只要不超過流的容量就可以繼續往流上提交數據,另一端只要流上有數據就可以讀取,而不管這個數據的開頭和結尾;數據報模式,有嚴格的次序關系和數據報的分割關系。而這兩種的不同大概是由於TCP一個套接字只接收來自一個對象的數據,而UDP套接字可以接收來自任意對象的數據。
兩者在模式上的不同,導致兩者在效率和應用模式上的不同。
在每個數據都要分析的情況下,例如發送一條配置命令,TCP必須約定消息頭格式指出這條消息的大小,而UDP不需要。而在流媒體數據上,由於TCP有數據重組的特性,效率相對UDP更高。