网络编程之 TCP / UDP 及其流程比较
TCP與UDP的區(qū)別
1、基于連接與無(wú)連接 2、對(duì)系統(tǒng)資源的要求(TCP較多,UDP少) 3、UDP程序結(jié)構(gòu)較簡(jiǎn)單 流模式與數(shù)據(jù)報(bào)模式4、TCP保證數(shù)據(jù)正確性,UDP可能丟包
5、TCP保證數(shù)據(jù)順序,UDP不保證
具體編程時(shí)的區(qū)別
1、socket()的參數(shù)不同 2、UDP Server不需要調(diào)用listen和accept 3、?UDP收發(fā)數(shù)據(jù)用sendto/recvfrom函數(shù) TCP:地址信息在connect/accept時(shí)確定UDP:在sendto/recvfrom函數(shù)中每次均 需指定地址信息 UDP:shutdown函數(shù)無(wú)效
部分滿足以下幾點(diǎn)要求時(shí),應(yīng)該采用UDP 面向數(shù)據(jù)報(bào)方式
1、網(wǎng)絡(luò)數(shù)據(jù)大多為短消息 2、擁有大量Client 對(duì)數(shù)據(jù)安全性無(wú)特殊要求 3、?網(wǎng)絡(luò)負(fù)擔(dān)非常重,但對(duì)響應(yīng)速度要求高 4、UDP協(xié)議是不可靠的網(wǎng)絡(luò)協(xié)議,它在通信兩端各建立一個(gè)Socket,但是這兩個(gè)Socket之間沒(méi)有虛擬鏈路,這兩個(gè)Socket只負(fù)責(zé)發(fā)送和接收數(shù)據(jù)報(bào)的對(duì)象! 例子:ICQ、ping???面向連接的TCP的流方式
服務(wù)器程序流程(多進(jìn)程):
1、程序初始化 2、填寫(xiě)本機(jī)地址信息 3、綁定并監(jiān)聽(tīng)一個(gè)固定的端口 4、收到Client的連接后建立一個(gè)socket連接 產(chǎn)生一個(gè)新的進(jìn)程與Client進(jìn)行通信和信息處理 5、子通信結(jié)束后中斷與Client的連接客戶端程序流程:
1、程序初始化 2、填寫(xiě)服務(wù)器地址信息 3、?連接服務(wù)器 4、與服務(wù)器通信和信息處理 5、通信結(jié)束后斷開(kāi)連接服務(wù)器代碼
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define MYPORT 3490????????????????
#define BACKLOG 10????????????????
void main() {
int sockfd, new_fd;????????????
struct sockaddr_in sa;???//本機(jī)地址?????
struct sockaddr_in their_addr;//遠(yuǎn)程地址
int sin_size;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
sa.sin_family = AF_INET;
sa.sin_port = htons(MYPORT);????????
sa.sin_addr.s_addr = INADDR_ANY;????
bzero(&(sa.sin_zero), 8);????????????
if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
?
while(1) {
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size))
if (new_fd == -1) {
perror("accept");
continue;
}
printf(”Got connection from %sn", inet_ntoa(their_addr.sin_addr));
if (fork() == 0) {
?
if (send(new_fd, "Hello, world! n", 14, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
?
while(waitpid(-1,NULL,WNOHANG) > 0);
}
}
?
?
客戶端代碼
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PORT 3490
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr;//服務(wù)器地址
if (argc != 2) {
fprintf(stderr,"usage: client hostnamen");
exit(1);
}
?
if ((he=gethostbyname(argv[1])) == NULL) {
?
herror("gethostbyname");
exit(1);
}
if ((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero), 8);
if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
perror("connect");
exit(1);
}
if ((numbytes=recv(sockfd,buf,MAXDATASIZE,0))==-1) {
perror("recv");
exit(1);
}
buf[numbytes] = '';
printf("Received: %s",buf);
close(sockfd);
return 0;
}
?
?
服務(wù)器程序流程(單進(jìn)程):
1、程序初始化 2、填寫(xiě)本機(jī)地址信息 3、綁定一個(gè)固定的端口 3、收到Client的數(shù)據(jù)報(bào)后進(jìn)行處理與通信 4、通信結(jié)束后斷開(kāi)連接客戶端程序流程:
1、程序初始化 2、填寫(xiě)服務(wù)器地址信息 3、連接服務(wù)器 與服務(wù)器通信和信息處理 //發(fā)送報(bào)文的方式建立與服務(wù)器的聯(lián)系 4、通信結(jié)束后斷開(kāi)連接UDP方式下服務(wù)器與客戶端程序差別不大,僅第三步不同。
?
服務(wù)器
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define MYPORT 3490
void main()
{
int sockfd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size, retval;
char buf[128];
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(my_addr.sin_zero), 8);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1) {
perror("bind");
exit(1);
}
?
while(1) {
retval = recvfrom(sockfd, buf, 128, 0, (struct sockaddr *)&their_addr, &sin_size);//獲取遠(yuǎn)程主機(jī)的報(bào)文,并解析
printf("Received datagram from %sn",inet_ntoa(their_addr.sin_addr));
if (retval == 0) {
perror (“recvfrom");
close(sockfd);
break;
}
retval = sendto(sockfd, buf, 128, 0, (struct sockaddr *)&their_addr, sin_size);
}
}
?
客戶端
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PORT 3490
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, numbytes, sin_size;
char buf[MAXDATASIZE] = “Hello, world!”;
struct hostent *he; //
struct sockaddr_in their_addr;//服務(wù)器地址
if (argc != 2) {
fprintf(stderr,"usage: client hostnamen");
exit(1);
}
?
if ((he=gethostbyname(argv[1])) == NULL) {
herror("gethostbyname");
exit(1);
}
if ((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1) {
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero), 8);
numbytes = sendto(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&their_addr,sizeof(their_addr));//向服務(wù)器發(fā)送任一報(bào)文
if (numbytes == -1) {
perror(“sendto");
exit(1);
}
printf(“Send: %s",buf);
numbytes = recvfrom(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&their_addr, &sin_size);
if (numbytes == -1) {
perror("recvfrom");
exit(1);
}
buf[numbytes] = '';
printf("Received: %s",buf);
close(sockfd);
return 0;
}
總結(jié)
以上是生活随笔為你收集整理的网络编程之 TCP / UDP 及其流程比较的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hihocoder1477 闰秒
- 下一篇: PPT进阶攻略