UDP程式設計以及與TCP的區別
阿新 • • 發佈:2018-12-22
UDP程式設計函式原型:
int socket(int domain, int type, int protocol); int bind(int sockfd, const struct sockaddr* my_addr, int addrlen); /* 與TCP函式原型一樣,參見上一篇部落格。 */ int recvfrom(int sockfd, void* buf, int len, int flags, struct sockaddr* src_addr, int *addrlen); /* 在recv的基礎上加上了後兩個引數,因為UDP通訊沒有連線的概念,所以每次讀取資料都需要獲取傳送端的socket地址,即引數src_addr所指的內容,addrlen引數為指定地址的長度。 */ int sendto(int sockfd, const void* buf, int len, int flags, const struct sockaddr* dest_addr, int addrlen); /* 在send的基礎上加上了指定接收端的socket地址dest_addr,addrlen引數指定該地址的長度。 */ int close(int sockfd);
UDP程式設計:
伺服器udpser.c
#include<stdio.h> #include<string.h> #include<assert.h> #include<stdlib.h> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> #include<unistd.h> int main() { int sockfd = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in ser, cli; memset(&ser, 0, sizeof(ser)); ser.sin_family = AF_INET; ser.sin_port = htons(6500); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); int len = sizeof(struct sockaddr_in); int res = bind(sockfd, (struct sockaddr*)&ser, len); assert(res != -1); char buff[128] = { 0 }; while (1) { recvfrom(sockfd, buff, 127, 0, (struct sockaddr*)&cli, &len); printf("%s", buff); sendto(sockfd, "OK", 3, 0, (struct sockaddr*)&cli, len); } close(sockfd); return 0; }
客戶端udpcli.c
#include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> #include<unistd.h> #include<stdlib.h> #include<assert.h> #include<stdio.h> #include<string.h> int main(int argc, char *argv[]) { if (argc < 3) { printf("error\n"); exit(0); } int sockfd = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in cli; memset(&cli, 0, sizeof(cli)); const char *ip = argv[1]; cli.sin_family = AF_INET; cli.sin_port = htons(atoi(argv[2])); cli.sin_addr.s_addr = inet_addr(ip); char buff[128] = { 0 }; int len = sizeof(cli); printf("start writing\n"); while (1) { fgets(buff, 127, stdin); if (strncmp(buff, "end", 3) == 0) { sendto(sockfd, "one cli end\n", 12, 0, (struct sockaddr*)&cli, len); sleep(1); break; } sendto(sockfd, buff, 127, 0, (struct sockaddr*)&cli, len); recvfrom(sockfd, buff, 127, 0, (struct sockaddr*)&cli, &len); printf("%s\n", buff); } close(sockfd); return 0; }
TCP和UDP的區別:
TCP:TCP是面向連線,較為可靠的位元組流服務。所謂位元組流服務,就是傳送資料的次數與接收資料的次數沒有關係,底層資料傳送或接收時,資料可能會被分開或者合併。
如圖:
UDP:UDP是無連線,相對TCP較為不可靠的資料報服務。傳送次數和接收次數相等,所以可能造成,如果一次未將資料讀完,UDP報文段中的資料將丟失。
如圖:
資料的可靠性傳輸:
①所有資料都能到達對端(確認機制和超時重傳機制)
②資料不亂序(TCP報頭中的序號)
③資料不出錯(16位的校驗和,校驗TCP頭部和資料部分)。
詳細TCP頭部結構解釋參見《Linux高效能伺服器程式設計》3.2。