对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);
}
时间: 2024-08-28 21:55:49

对UDP socket缓冲区的理解的相关文章

Linux编程之UDP SOCKET全攻略

这篇文章将对linux下udp socket编程重要知识点进行总结,无论是开发人员应知应会的,还是说udp socket的一些偏僻知识点,本文都会讲到.尽可能做到,读了一篇文章之后,大家对udp socket有一个比较全面的认识.本文分为两个专题,第一个是常用的upd socket框架,第二个是一些udp socket并不常用但又相当重要的知识点. 一.基本的udp socket编程 1. UDP编程框架要使用UDP协议进行程序开发,我们必须首先得理解什么是什么是UDP?这里简单概括一下. UD

UDP Socket

UDP的Java支持 UDP协议提供的服务不同于TCP协议的端到端服务,它是面向非连接的,属不可靠协议,UDP套接字在使用前不需要进行连接.实际上,UDP协议只实现了两个功能: 1)在IP协议的基础上添加了端口: 2)对传输过程中可能产生的数据错误进行了检测,并抛弃已经损坏的数据. Java通过DatagramPacket类和DatagramSocket类来使用UDP套接字,客户端和服务器端都通过DatagramSocket的send()方法和receive()方法来发送和接收数据,用Datag

Java TCP/UDP socket 编程流程总结

最近正好学习了一点用java socket编程的东西.感觉整体的流程虽然不是很繁琐,但是也值得好好总结一下. Socket Socket可以说是一种针对网络的抽象,应用通过它可以来针对网络读写数据.就像通过一个文件的file handler就可以都写数据到存储设备上一样.根据TCP协议和UDP协议的不同,在网络编程方面就有面向两个协议的不同socket,一个是面向字节流的一个是面向报文的. 对socket的本身组成倒是比较好理解.既然是应用通过socket通信,肯定就有一个服务器端和一个客户端.

Python Udp Socket

socket(套接字),传输层通信的端点,由IP和端口号组成(IP,Port),可以通过socket精确地找到服务器上的进程并与之通信 python2.6实现,基于AF_INET(网络套接字) 类型SOCKET_STREAM(TCP套接字),SOCKET_DGRAM(UDP套接字) UDP socket实现较TCP要简单,没有建立连接的过程,服务端无限循环接收数据,处理数据返回,客户端也无需建立通信连接, 直接发送数据接收数据即可 UDP socket通信逻辑 UDP服务端:创建socket>>

【Java TCP/IP Socket】UDP Socket(含代码)

转载请注明出处:http://blog.csdn.net/ns_code/article/details/14128987 UDP的Java支持 UDP协议提供的服务不同于TCP协议的端到端服务,它是面向非连接的,属不可靠协议,UDP套接字在使用前不需要进行连接.实际上,UDP协议只实现了两个功能: 1)在IP协议的基础上添加了端口: 2)对传输过程中可能产生的数据错误进行了检测,并抛弃已经损坏的数据. Java通过DatagramPacket类和DatagramSocket类来使用UDP套接字

Java UDP Socket编程

UDP协议 UDP协议提供的服务不同于TCP协议的端到端服务,它是面向非连接的,属不可靠协议,UDP套接字在使用前不需要进行连接.实际上,UDP协议实现了两个功能: 1)在IP协议的基础上添加了端口: 2)对传输过程中可能产生的数据错误进行了检测,并抛弃已经损坏的数据. UDP的Java支持 Java通过DatagramPacket类和DatagramSocket类来使用UDP套接字,客户端和服务器端都通过DatagramSocket的send()方法和receive()方法来发送和接收数据,用

Socket缓冲区

1.由于可读状态是在对方写入数据后或socket关闭时才能出现,因此如果客户端和服务端都停留在read时,如果没有任何一方,向对方写入数据,这将会产生一个死锁. 2.此外,在本地接收操作发起之前,很可能接收缓冲区中已经有数据了,这是一种异步.不要误以为,本地调用接收操作后,对方才会发送数据,实际数据何时到达,本地不能做出任何假设. 3. Java提供了便捷的网络编程模式,尤其在套接字中,直接提供了与网络进行沟通的输入和输出流,用户对网络的操作就如同对文件操作一样简便.在客户端与服务端建立Sock

TCP与UDP收发的时候TCP有缓冲区还是UDP有缓冲区,使用它们时该注意什么?

问题:TCP与UDP收发的时候TCP有缓冲区还是UDP有缓冲区,使用它们时该注意什么? (一)基础 1.TCP为可靠链接,分三次握手四次释放. 2.UDP为不可靠链接 (二)TCP与UDP的输出每 个TCP套接口有一个发送缓冲区,可以用SO_SNDBUF套接口选项来改变这一缓冲区的大小.当应用进程调用write往套接口写数据时,内核从应用进 程缓冲区中拷贝所有数据到套接口的发送缓冲区,如果套接口发送缓冲区容不下应用程序的所有数据,或者是应用进程的缓冲区大于套接口的发送缓冲区,或者是套 接口的发送

How To: Perl TCP / UDP Socket Programming using IO::Socket::INET

http://www.thegeekstuff.com/2010/07/perl-tcp-udp-socket-programming/ In this article, let us discuss how to write Perl socket programming using the inbuilt socket modules in Perl. Perl socket modules provides an object interface that makes it easier