概述
最近在看一个关于UDP通信的实例的程序,从中对UDP通信有了一些不一样的认识,之前对udp与tcp的区别只是停留在下面这样宏观的认知上
1、TCP面向连接(如打电话要先拨号建立连接)。
UDP是无连接的,即发送数据之前不需要建立连接。
2、安全方面的区别TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达。UDP尽最大努力交付,即不保证可靠交付。
从上面的区别来看,在一般的编程当中当然是tcp更加可靠一点,而我在实际中也是这样做的,写过的网络程序中几乎所有的都是TCP协议来传输数据的,但是在写程序的过程中也遇到一些头疼的事情,
1、tcp的面向连接的,那么一旦当连接异常终止的时候就会有一些意向不到的事情发生,而我也是经常在此花费巨大的代价去解决这个问题。
2、tcp是点对点的通信,当需要建立并发服务器的时候我经常使用多线程的机制来完成,这无形中增加了性能的损耗(这一点不重要哈!)。
我在最近这段时间接触UDP通信中,发现了一些它的特点
1、udp通信不存在上面我所描述的连接问题,因为它毕竟是无连接嘛(好像是一句废话),不过这样就不需要花费时间来处理这个问题了,很爽是不是。
2、在写tcp通信的时候我们都知道里边有server端和client端的区分,也就是我们常说的C/S架构,但是在udp中这样的概念好像很模糊,或者说根本不存在,先看一个小例子吧
server.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
typedef struct sockaddr* saddrp;
int main(int argc, char const *argv[])
{
//创建socket
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if (0 > sockfd)
{
perror("sockfd");
return -1;
}
// server端的地址信息
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(5577); //端口号
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //我的ip地址
// 将地址信息绑定到socket上
int ret = bind(sockfd,(saddrp)&addr,sizeof(addr));
if (0 > ret)
{
perror("bind");
return -1;
}
// client端的地址信息
socklen_t addr_len = sizeof(struct sockaddr_in);
struct sockaddr_in addr_i = {};
addr_i.sin_family = AF_INET;
addr_i.sin_port = htons(7755);
addr_i.sin_addr.s_addr = inet_addr("127.0.0.1");
while(1){
char buf[255] = {};
recvfrom(sockfd,buf,sizeof(buf),0,(saddrp)&addr,&addr_len); // 使用server端的地址信息接收信息
printf("Recv:%sn",buf);
if(0 == strcmp(buf,"q")) break;
sendto(sockfd,buf,strlen(buf)+1,0,(saddrp)&addr_i,addr_len); // 使用client端的地址信息发送信息
printf("send ok!n");
}
//关闭socket对象
close(sockfd);
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
typedef struct sockaddr* saddrp;
int main(int argc, char const *argv[])
{
// 创建socket
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if (0 > sockfd)
{
perror("socket");
return -1;
}
// client 端的地址信息
struct sockaddr_in addr_i = {};
addr_i.sin_family = AF_INET;
addr_i.sin_port = htons(7755);
addr_i.sin_addr.s_addr = inet_addr("127.0.0.1");
// 绑定
int ret = bind(sockfd,(saddrp)&addr_i,sizeof(addr_i));
if (0 > ret)
{
perror("bind");
return -1;
}
// server端的地址信息
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(5577);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
socklen_t addr_len = sizeof(struct sockaddr_in);
while(1)
{
char buf[255] = {};
char buf1[255] = {};
printf("Please input the return value:");
fgets(buf,255,stdin);
buf[strlen(buf) - 1] = '