UDP基础知识

UDP(User Datagram Protocol,用户数据报协议)是一个简单的、面向数据报的无连接协议,提供了快速但不一定可靠的传输服务。

  UDP与TCP相比主要有以下区别。

    1.UDP速度比TCP快

      由于UDP不需要先与对方建立连接,也不需要传输确认,因此其数据传输速度比TCP快得多。

    2.UDP有消息边界

      使用UDP不需要考虑消息边界问题,使用上比TCP简单

    3.UDP可以一对多传输

      利用UDP可以使用广播或组播的方式同时向子网上的所有客户发送信息。这一点也比TCP方便。

    4.UDP可靠性不如TCP

      与TCP不同,UDP并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP称为不可靠的传输协议。

    5.UDP不像TCP那样能保证有序传输

      UDP不能确保数据的发送和接收顺序。对于突发性的数据报,有可能会乱序。事实上,UDP的这种乱序性基本上很少出现,通常只会在网络非常拥挤的情况下才有可能发生

UDP编程

 1)创建socket时,数据格式为:SOCK_DGRAM(数据块)

 2)数据收发用recvfrom和sendto

          ssize_t recvfrom(int socket,void *restrict buffer,size_t length,int flags,struct sockaddr * restrict address,socklen_t *restrict address_len);

           restrict:类型限定符,限定约束指针。表明该指针是访问这个数据队形的唯一的方式

            补充一点:

               void *memcpy( void * restrict dest ,const void * restrict src,sizi_t n) 这是一个很有用的内存复制函数,由于两个参数都加了restrict限定,所以两块区域不能重叠,即 dest指针所指的区域,不能让别的指针来修改,即src的指针不能修改. 相对应的别一个函数 memmove(void *dest,const void * src,size_t)则可以重叠。

          socket:  已连接的套接字

          buffer:接收数据的缓冲区

          length:缓冲区长度

           flags  :调用操作方式

           address:指向装有源地址的缓冲区(传出型参数)

           address_len:指向源地址缓冲区的实际长度(传入传出型参数)

          ssize_t sendto(int socket,const void*buffer,size_t length,int flags,struct sockaddr* dest_addr,socklen_t len);

             socket:已连接套接字

             buffer:包含待发送数据的缓冲区

             length:buffer缓冲区数据的长度

             flags:调用方式标志位

             dest_addr:指向目的套接字的地址

           len:dest_addr所指地址的长度

代码:

server.c

#include 
#include 
#include 
#include 
#include 
#include 
#define SIZE 1024int main(int argc,char *argv[]){  if(argc!=3)  {    printf("enter [IP],[PORT]\n");  }  int fd=socket(AF_INET,SOCK_DGRAM,0);  if(fd<0)  {    perror(socket);    return 1;  }  struct sockaddr_in local;  int port=atoi(argv[2]);  local.sin_family=AF_INET;  local.sin_port=htons(port);  local.sin_addr.s_addr=inet_addr(argv[1]);  if(bind(fd,(struct socketaddr*)&local,sizeof(local))<0)  {    perror("bind");    return 2;  } struct sockaddr_in remote; socklen_t len=sizeof(remote);  while(1)  {    char buf[SIZE];    memset(buf,'\0',sizeof(buf));    ssize_t _s=recvfrom(fd,buf,sizeof(buf)-1,0,(struct socketaddr *)&remote,&len);    if(_s>0)    {      buf[_s]='\0';      printf("client:[ip:%s][port:%d] %s",inet_ntoa(remote.sin_addr),ntohs(remote.sin_port));    }    else if(_s==0)    {      printf("read done..\n");      break;    }    else{      break;    }  }  close(fd);  return 0;}

client.c

#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc,char *argv[]){  if(argc!=3)  {     printf("[ip][port]\n");    return 1;  }  int fd=socket(AF_INET,SOCK_DGRAM,0);  if(fd<0)  {    perror("socket");    return 2;  }  int port=atoi(argv[2]);  struct sockaddr_in remote;  remote.sin_family=AF_INET;  remote.sin_port=htons(port);  remote.sin_addr.s_addr=inet_addr(argv[1]);  while(1)  {    char buf[1024];    memset(buf,'\0',sizeof(buf)-1);    ssize_t _ss=read(0,buf,sizeof(buf)-1);     if(_s>0) { buf[_s]='\0'; }    ssize_t _s=sendto(fd,buf,sizeof(buf)-1,0,(struct sockaddr *)&remote,sizeof(remote));  }  return 0;}