一、协议区别
UDP协议
面向无连接(如发邮件,不用通知对方,直接发出去,至于对方有没有收到就不管了)的用户数据报协议,在传输数前
不需要先建立连接;目地主机的运输层收到UDP报文后,不需要给出任何确认
1.相比TCP速度稍快些;
2.编程简单,占用系统资源低;
3.支持广播和多播,可以一对一,一对多,多对一和多对多的交互通信;
4.UDP首部只需8个字节;
5.UDP应用:拥有大量client,对数据安全性无特殊要求,网络负担非常重,但对相应速度要求高。比如:DNS(域名解析)、
NFS(网络文件系统)、RTP(流媒体)等.
TCP协议
面向连接(如打电话要先拨号建立连接,拨通之后才可以说话)的流式协议;可靠、有序、出错重传、且每收到一个数据都
要给出相应的确认
1.不支持广播和多播,每条TCP连接只能是点到点;
2.建立连接时需要三次握手,断开连接时需要四次挥手;
3.TCP首部需要20字节;
4.TCP应用:对网络通信质量有要求,整个数据要求准确无误时。比如:HTTP、HTTPS、FTP等传输文件的协议,POP、
SMTP等邮件传输协议.
二、编程区别
UDP服务端编程步骤:
1.创建一个socket,用函数socket();
2.绑定IP地址、端口等信息到socket上,用函数bind();
3.循环接收数据,用函数recvfrom();
4.关闭网络连接。
5.代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { unsigned short port = 8008; int sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字 if(sockfd < 0) { perror("socket"); exit(-1); } struct sockaddr_in my_addr; //定义本地信息结构体 bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(port); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //htonl()将32位主机字节序数据转换成网络字节序数据 printf("Binding server to port %d\n", port); int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)); //绑定本地信息(IP、端口号) if(err_log != 0) { perror("bind"); close(sockfd); exit(-1); } printf("receive data...\n"); while(1) { int recv_len; char recv_buf[512] = ""; struct sockaddr_in client_addr; //定义接收客户端信息结构体 char cli_ip[INET_ADDRSTRLEN] = "";//INET_ADDRSTRLEN=16 socklen_t cliaddr_len = sizeof(client_addr); recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &cliaddr_len); //接收数据 inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN); //将32位无符号整数转换成点分十进制数串 printf("\nip:%s ,port:%d\n",cli_ip, ntohs(client_addr.sin_port)); printf("data(%d):%s\n",recv_len,recv_buf); } close(sockfd); return 0; }
UDP客户端编程步骤:
1.创建一个socket,用函数socket();
2.发送数据,用函数sendto();
3.关闭网络连接。
4.代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { unsigned short port = 8008; char *server_ip = "192.168.1.2"; int sockfd = socket(AF_INET, SOCK_DGRAM, 0); //创建UDP套接字 if(sockfd < 0) { perror("socket"); exit(-1); } struct sockaddr_in dest_addr; //定义服务器信息结构体 bzero(&dest_addr, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(port); inet_pton(AF_INET, server_ip, &dest_addr.sin_addr); printf("send data to UDP server %s:%d!\n", server_ip, port); while(1) { char send_buf[512] = ""; fgets(send_buf, sizeof(send_buf), stdin);//获取输入 send_buf[strlen(send_buf)-1] = '\0'; sendto(sockfd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));//发送数据 } close(sockfd); return 0; }
TCP服务端编程步骤:
1.创建一个socket,用函数socket();
2.绑定IP地址、端口等信息到socket上,用函数bind();
3.开启监听,用函数listen();
4.接收客户端上来的连接,用函数accept();
5.收发数据,用函数send()和recv(),或者read()和write();
6.关闭网络连接;
7.关闭监听。
8.代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { unsigned short port = 8008; struct sockaddr_in my_addr; //定义本地信息结构体 bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(port); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)); if( err_log != 0) { perror("binding"); close(sockfd); exit(-1); } err_log = listen(sockfd, 10); if(err_log != 0) { perror("listen"); close(sockfd); exit(-1); } printf("listen client @port=%d...\n",port); while(1) { struct sockaddr_in client_addr; //定义接收客户端信息结构体 char cli_ip[INET_ADDRSTRLEN] = ""; socklen_t cliaddr_len = sizeof(client_addr); int connfd; connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len); if(connfd < 0) { perror("accept"); continue; } inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN); printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port)); char recv_buf[2048] = ""; while( recv(connfd, recv_buf, sizeof(recv_buf), 0) > 0 ) //接收数据 { printf("\nrecv data:\n"); printf("%s\n",recv_buf); } close(connfd); //关闭已连接套接字 printf("client closed!\n"); } close(sockfd); //关闭监听套接字 return 0; }
TCP客户端编程步骤:
1.创建一个socket,用函数socket();
2.连接服务器,用函数connect();
3.收发数据,用函数send()和recv(),或者read()和write();
4.关闭网络连接。
5.代码
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> int main(int argc, char *argv[]) { unsigned short port = 8008; // 服务器的端口号 char *server_ip = "192.168.1.2"; // 服务器ip地址 int sockfd = socket(AF_INET, SOCK_STREAM, 0);// 创建TCP套接字 if(sockfd < 0) { perror("socket"); exit(-1); } struct sockaddr_in server_addr; //定义服务器信息结构体 bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); inet_pton(AF_INET, server_ip, &server_addr.sin_addr); int err_log = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); // 主动连接服务器 if(err_log != 0) { perror("connect"); close(sockfd); exit(-1); } char send_buf[512] = ""; printf("send data to %s:%d\n",server_ip,port); while(1) { printf("send:"); fgets(send_buf,sizeof(send_buf),stdin); send_buf[strlen(send_buf)-1]='\0'; send(sockfd, send_buf, strlen(send_buf), 0); // 向服务器发送信息 } close(sockfd); return 0; }
C/S架构图: