一、协议区别
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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
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架构图: