首页 > 代码库 > 对UDP socket缓冲区的理解
对UDP socket缓冲区的理解
对UDP socket缓冲区的理解
UDP套接字的收发报文要用sendto 和 recvfrom,可以类比TCP套接字的connect和accept,参数里面会标识要发往的对端,或者要接收的对端的IP地址和端口;对UDP套接字connect的行为也只是告诉内核:“帮我做个过滤,我只关心这个对端的报文”,已连接的UDP套接字上可以利用read, write, recv, send函数,通常如果确定了该实体只与一个对端进行通信,那么就选择connect;更重要的是UDP套接字的缓冲区是以一个个报文为单位进行排队的,调用一次recvfrom表示提取一个报文,和TCP基于字节流的方式是不同的。基于这样的原因我们不能在UPD中先读取一定的应用层header,而后在根据头部中长度字段来优雅的读取具体的数据,这样会出错,发生混乱;而在TCP中经常会这么做。
下面是个例子,客户端以一定长度的内容进行发送,客户端进行接收,先读取首部,而后是具体的数据块,如果用UDP是会出错的。利用TCP可以,代码如下(完整代码可以看这里file-transfer):
typedef struct{ unsigned char fp[20]; int chunk_id; short flags; short chunk_len; char data[0]; }TransferUnit; // some flags for this chunk transfered. enum{ UNIT_NEED_DEDU = 0x0001, // need deduplication UNIT_FILE_START = 0x0002, // first gram , file metadata UNIT_FILE_END = 0x0004, CHUNK_OTHER = 0x0008, // other for extension }; void recvFile(char name[20],int sockfd){ int ret,fd; mode_t fdmode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); unsigned char mesg[MAX]; fd_set rdset; struct timeval tv; int rlen, wlen, chunklen; int i; TransferUnit *header = (TransferUnit *)malloc(sizeof(TransferUnit)); fd = open(name,O_RDWR|O_CREAT|O_APPEND,fdmode); if(fd == -1) { printf("open file %s error:%s \n",name,strerror(errno)); exit(-1); } while(1){ memset(mesg, 0, sizeof(mesg)); // read the gram header first rlen = read(sockfd, header, sizeof(TransferUnit)); //printf("%d\n", rlen); if(rlen != sizeof(TransferUnit) ){ printf("read sockfd error %s\n",strerror(errno)); exit(-1); } // recv file end if((header->flags ^ UNIT_FILE_END) == 0){ printf("recv end.\n"); break; } // recv file metadata if((header->flags ^ UNIT_FILE_START) == 0){ int len = header->chunk_len; // metadata length... char metadata[100] = {0}; printf("==== begin file recv ====,metadata len = %d\n", len); if((rlen = read(sockfd, mesg, len)) == len){ mesg[len] = '\0'; printf("File name : %s\n", mesg); } continue; } chunklen = header->chunk_len; // read the actual chunk data rlen = read(sockfd, mesg, chunklen); //printf("chunk_id:%d,chunk_len:%d \n", header->chunk_id, header->chunk_len); if(rlen != chunklen ){ printf("read chunk data error %s\n",strerror(errno)); exit(-1); } // write the chunk data to this file wlen = write(fd,mesg,rlen); if(wlen != rlen ){ printf("write error %s\n",strerror(errno)); exit(-1); } printf("The %d times write\n",i); } close(fd); }
对UDP socket缓冲区的理解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。