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;}