UDP和TCP兩大協議的區別,讓(rang)你快速高效掌握
時間(jian):2018-06-14 來源:未知
UDP和TCP兩大協(xie)議的區別(bie)
談起UDP與TCP兩大協議(yi)的(de)(de)異同,有人說我喜歡(huan)用(yong)(yong)(yong)TCP不(bu)喜歡(huan)用(yong)(yong)(yong)UDP,也有人說我喜歡(huan)用(yong)(yong)(yong)UDP而不(bu)喜歡(huan)用(yong)(yong)(yong)TCP,使(shi)用(yong)(yong)(yong)TCP的(de)(de)人說,我使(shi)用(yong)(yong)(yong)使(shi)用(yong)(yong)(yong)的(de)(de)協議(yi)比(bi)(bi)較(jiao)可(ke)靠、不(bu)容易粘(zhan)包、不(bu)容易丟包;使(shi)用(yong)(yong)(yong)UDP的(de)(de)人說,我使(shi)用(yong)(yong)(yong)的(de)(de)協議(yi)操作簡單、傳輸(shu)速度比(bi)(bi)較(jiao)快;我想說的(de)(de)是各(ge)(ge)有各(ge)(ge)的(de)(de)好處與不(bu)足。下面就讓(rang)四哥給大家講講他們的(de)(de)優缺點(dian)與重要的(de)(de)區別,然(ran)后在選擇適合自己的(de)(de)協議(yi)進(jin)行(xing)開發吧。
一、TCP與UDP基本(ben)區別
1.基于(yu)連(lian)接與(yu)無(wu)連(lian)接
2.TCP要求系(xi)統資源較多,UDP較少;
3.UDP程序結(jie)構較簡單
4.流模式(TCP)與(yu)數(shu)據報(bao)模式(UDP);
5.TCP保證數據正確性(xing),UDP可能丟包
6.TCP保(bao)證(zheng)數據順序(xu),UDP不保(bao)證(zheng)
二、UDP應用場景(jing):
1.面向(xiang)數據報方(fang)式
2.網(wang)絡數據大多為短消息
3.擁(yong)有大量Client
4.對數據安全(quan)性無(wu)特殊要(yao)求
5.網(wang)絡(luo)負(fu)擔非常重,但對響應速度要求高
三、具體編(bian)程時的區別
1.socket()的參(can)數不同
2.UDP Server不需要調用listen和accept
3.UDP收(shou)發數(shu)據用sendto/recvfrom函數(shu)
4.TCP:地址信息在(zai)connect/accept時確定
5.UDP:在sendto/recvfrom函數中(zhong)每次均需指定地址信(xin)息
6.UDP:shutdown函數(shu)無效
7.UDP不需要(yao)經過三次(ci)握手與四次(ci)揮手的過程
編程區別
通(tong)常我(wo)(wo)們(men)在說(shuo)到網(wang)絡(luo)編(bian)程時默認是(shi)指TCP編(bian)程,即用前面(mian)提到的socket函數創建(jian)一個(ge)socket用于(yu)TCP通(tong)訊,函數參數我(wo)(wo)們(men)通(tong)常填(tian)為SOCK_STREAM。即socket(PF_INET, SOCK_STREAM, 0),這表示建(jian)立(li)一個(ge)socket用于(yu)流式(shi)網(wang)絡(luo)通(tong)訊。
SOCK_STREAM這種(zhong)的特點(dian)是(shi)面向連接的,即(ji)每(mei)次收(shou)發數據之前必須通過connect建立連接,也是(shi)雙向的,即(ji)任何一方都可以(yi)收(shou)發數據,協議(yi)本身提供(gong)了一些(xie)保障機制保證它是(shi)可靠的、有序的,即(ji)每(mei)個(ge)包(bao)按照發送的順(shun)序到達接收(shou)方。
而SOCK_DGRAM這種是(shi)(shi)User Datagram Protocol協議的(de)(de)網(wang)絡通訊,它是(shi)(shi)無(wu)連接(jie)的(de)(de),不(bu)(bu)可靠的(de)(de),因為通訊雙(shuang)方(fang)發送數(shu)(shu)據(ju)(ju)后不(bu)(bu)知道(dao)對方(fang)是(shi)(shi)否已經收(shou)到(dao)數(shu)(shu)據(ju)(ju),是(shi)(shi)否正常收(shou)到(dao)數(shu)(shu)據(ju)(ju)。任(ren)何一方(fang)建(jian)立一個socket以后就可以用(yong)sendto發送數(shu)(shu)據(ju)(ju),也可以用(yong)recvfrom接(jie)收(shou)數(shu)(shu)據(ju)(ju)。根本不(bu)(bu)關心對方(fang)是(shi)(shi)否存在,是(shi)(shi)否發送了數(shu)(shu)據(ju)(ju)。它的(de)(de)特點是(shi)(shi)通訊速(su)度比較快。大(da)家都(dou)知道(dao)TCP是(shi)(shi)要經過三次握手的(de)(de),而UDP沒(mei)有。
基于(yu)上(shang)述不(bu)同,UDP和TCP編程步(bu)驟也有些不(bu)同,如下:
TCP:
TCP編程的服務(wu)器(qi)端一般步驟是:
1、創建一個(ge)socket,用函數socket();
2、設置socket屬性,用(yong)函數setsockopt(); * 可選
3、綁定IP地址、端(duan)口等(deng)信息(xi)到socket上,用函數bind();
4、開啟監聽,用函數(shu)listen();
5、接(jie)收(shou)客戶端上來的連接(jie),用函數accept();
6、收發數(shu)據,用函(han)數(shu)send()和(he)(he)recv(),或者(zhe)read()和(he)(he)write();
7、關閉網絡連接;
8、關閉(bi)監聽;
TCP編程的客戶端(duan)一般步驟是(shi):
1、創(chuang)建一個socket,用函數socket();
2、設(she)置socket屬(shu)性,用函數setsockopt();* 可選
3、綁定IP地(di)址(zhi)、端(duan)口等信(xin)息到socket上,用函數bind();* 可(ke)選
4、設(she)置要(yao)連接的對(dui)方的IP地(di)址和端口等屬性;
5、連接服務器,用函數connect();
6、收發數據(ju),用函(han)數send()和recv(),或者read()和write();
7、關閉網絡連接;
UDP:
與之(zhi)對應的UDP編程步驟要簡(jian)單許多(duo),分別如下(xia):
UDP編程(cheng)的服務(wu)器端一(yi)般步(bu)驟(zou)是:
1、創建(jian)一個socket,用函數socket();
2、設(she)置socket屬性,用函數setsockopt();* 可(ke)選
3、綁定IP地址、端口等信(xin)息到socket上,用函數bind();
4、循環(huan)接收數據,用(yong)函(han)數recvfrom();
5、關閉(bi)網(wang)絡連(lian)接;
UDP編程的客戶端一(yi)般(ban)步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性(xing),用函數setsockopt();* 可(ke)選
3、綁定(ding)IP地址、端口等信息到socket上,用函數bind();* 可選(xuan)
4、設置對(dui)方(fang)的IP地(di)址和端口等(deng)屬性;
5、發送(song)數(shu)據,用函數(shu)sendto();
6、關閉(bi)網絡連接(jie);
TCP和(he)UDP是OSI模型中的運輸層中的協(xie)議(yi)。TCP提供可靠的通信傳(chuan)輸,而UDP則(ze)常被用于讓廣播和(he)細節控制交(jiao)給(gei)應(ying)用的通信傳(chuan)輸。
以下是他們具體的代(dai)碼的區別:
TCP編(bian)程代碼:
#include
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
#include
#define SERV_PORT 5001
#define SERV_IP "192.168.7.8"
#define QUIT_STR "quit"
int main (void)
{
int fd = -1, newfd = -1;
struct sockaddr_in sin;
/* 1.創建套接字fd */
if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { /* IPV4的TCP通信 */
perror ("socket");
exit (1);
}
/*2.1 填(tian)充(chong)sin結構體: 填(tian)寫(xie)IP地址和端(duan)口(kou)這兩(liang)個(ge)要素 */
bzero (&sin, sizeof (sin));
sin.sin_family = AF_INET;
sin.sin_port = htons (SERV_PORT); /* 網絡字節序的端口號 */
sin.sin_addr.s_addr = inet_addr (SERV_IP);
/* 2.2 綁定 */
if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
perror ("bind");
exit (1);
}
/*3. 把主(zhu)動套(tao)接(jie)字變為被(bei)動套(tao)接(jie)字 */
listen (fd, 5);
printf("Server starting....OK!\n");
/*4.阻(zu)塞等待客戶端連接 */
if ((newfd = accept (fd, NULL, NULL)) < 0) {
perror ("accept");
exit (1);
}
/*5.讀寫客(ke)戶端數據 */
while (1) {
char buf[BUFSIZ];
bzero (buf, BUFSIZ);
read (newfd, buf, BUFSIZ - 1);
printf ("Server Read: %s\n", buf);
if (!strncasecmp (buf, QUIT_STR, strlen (QUIT_STR))) { //客戶端輸入了quit
close (newfd);
break;
}
}
close (fd);
return 0;
}
UDP 服務器編程(cheng)代碼:
#include
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
#include
#include
#define SERV_PORT 5001
#define SERV_IP "192.168.7.8"
#define QUIT_STR "quit"
void usage (char *s)
{
printf ("Usage:\n");
printf ("\t%s [serv_port]\n", s);
printf ("\tserv_port: server port.\n");
printf ("\n");
}
int main (int argc, char *argv[])
{
int fd = -1;
struct sockaddr_in sin;
int port = SERV_PORT;
/*優化(hua)4: 參(can)數處(chu)理 */
if (argc != 1 && argc != 2) {
usage (argv[0]);
exit(1);
}
if (argc == 2) {
port = atoi (argv[1]);
}
/* 1.創建UDP套(tao)接字(zi)fd */
if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { /* IPV4的UDP通信 */
perror ("socket");
exit (1);
}
/*優(you)化1: 允許綁定的IP地址(zhi)和端口號(hao)能(neng)夠快速重用(yong) */
int b_reuse = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));
/*2.1 填(tian)充sin結構體: 填(tian)寫(xie)IP地(di)址(zhi)和端口這兩個要(yao)素(su) */
bzero (&sin, sizeof (sin));
sin.sin_family = AF_INET;
sin.sin_port = htons (port); /* 網絡字節(jie)序的端(duan)口號 */
sin.sin_addr.s_addr = htonl (INADDR_ANY); /*優化2: bind在任意IP */
/* 2.2 綁定 */
if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
perror ("bind");
exit (1);
}
printf ("UDP Server starting....OK!\n");
/*3.阻塞等(deng)待客戶端連接(jie) */
int ret = -1;
char buf[BUFSIZ];
struct sockaddr_in cin;
socklen_t clen = sizeof (cin);
while (1) {
bzero (buf, BUFSIZ);
do {
ret = recvfrom (fd, buf, BUFSIZ - 1, 0, (struct sockaddr *) &cin, &clen);
} while (ret < 0 && EINTR == errno);
if (ret < 0) {
perror ("recvfrom");
continue;
}
char cli_ipv4[16];
if (inet_ntop (AF_INET, (void *) &cin.sin_addr, cli_ipv4, sizeof (cin)) == NULL) {
perror ("inet_ntop");
continue;
}
printf ("Client(%s:%d) said: %s\n", cli_ipv4, ntohs (cin.sin_port), buf);
}
close (fd);
return 0;
}
TCP與UDP區(qu)別總結:
1、TCP面向(xiang)連接(如打電(dian)話要先撥(bo)號建立(li)連接);UDP是無連接的,即發(fa)送數據(ju)之前不需要建立(li)連接
2、TCP提供(gong)可靠的服務。也就是說,通(tong)過TCP連接傳送的數據(ju),無差錯,不丟失,不重(zhong)復,且按序(xu)到達(da);UDP盡(jin)最大(da)努力交付,即(ji)不保(bao) 證可靠交付
3、TCP面(mian)向(xiang)(xiang)字節流(liu),實際上是(shi)TCP把數據看成一連串(chuan)無(wu)結構的字節流(liu);UDP是(shi)面(mian)向(xiang)(xiang)報文的
UDP沒有(you)(you)擁塞控制,因此網絡出現擁塞不會使源主機(ji)的發送速率降低(對實時應(ying)用很有(you)(you)用,如IP電話,實時視頻會議等)
4、每(mei)一條TCP連接只能(neng)是點(dian)到(dao)點(dian)的(de)(de);UDP支持一對(dui)一,一對(dui)多(duo),多(duo)對(dui)一和多(duo)對(dui)多(duo)的(de)(de)交互通(tong)信
5、TCP首部開銷20字節;UDP的首部開銷小,只(zhi)有8個字節
6、TCP的邏輯通信(xin)(xin)(xin)信(xin)(xin)(xin)道(dao)是(shi)全雙(shuang)工的可(ke)靠信(xin)(xin)(xin)道(dao),UDP則是(shi)不可(ke)靠信(xin)(xin)(xin)道(dao)
來到(dao)這里(li)相信(xin)很多玩網絡編(bian)程的(de)(de)朋友已經(jing)了(le)(le)解甚至熟(shu)悉了(le)(le)他(ta)(ta)們區別(bie)(bie)和(he)用(yong)處了(le)(le),但是(shi)(shi)我還是(shi)(shi)有必(bi)要(yao)的(de)(de)重新提一下,沒有什(shen)么(me)東西(xi)是(shi)(shi)最(zui)好的(de)(de),這好與(yu)壞(huai)只是(shi)(shi)相對而(er)言(yan),遵循著相對論的(de)(de)基本(ben)轉折,因人而(er)異,適合自己(ji)的(de)(de)就好!現在UDP與(yu)TCP的(de)(de)區別(bie)(bie)懂了(le)(le),還需要(yao)了(le)(le)解一下他(ta)(ta)們里(li)面(mian)的(de)(de)具體(ti)協(xie)議(yi)和(he)細節哦(e),下集再會!

