Sending Files(Maps etc) Should I send multiple udp packets or use tcp?

Started by
7 comments, last by markr 17 years, 10 months ago
I gather if I use udp I have to do the following, Create a realiable ack message system using in order packets so the files are recieved in order. Split big files up into multiple packets so they don't exceed the udp limit. Rejoin the packets the reciever side. If I use tcp can I do the following? Create tcp stream (Using sockets internally), and send one big file packet over the size of the file and it will be ensured to reach it's destination in order. Should I first send a 4 byte value indicating the size of the file so I know when it's been fully recieved? Also if udp is your suggestion, can someone please tell me the udp packet size limit? I've only heard about the limit, not what it actually is.
Advertisement
I'd use TCP for that. It works the way you described.

Simulating TCP with UDP doesn't buy you anything in this case, to do better than TCP you would need to do some sophisticated stuff like using raptor codes. Advantage of raptor codes: some graphs

Edit:
The UDP packet size limit depends on the lower levels of the connection (Ethernet, wireless lan, whatever is used to actually transmit your packet), 1 UDP packet has to be delivered in one piece

[Edited by - Trap on June 7, 2006 2:51:06 PM]
If you are sending non-time sensitive information that needs to get there, then TCP is the way to go.

theTroll
Yes, I'd use TCP for this. There's no benefit to using UDP if you need a large contiguous data block sending. Smaller, non-sequential deliveries suit UDP. Packet size limit varies, you can test for the largest allowable packet size:

// Create a normal UDP socket.bool WSNormalSocket::createUDPNormalSocket(){	if (m_bReady)	{		m_pLog->log("WSNormalSocket %x failed to createUDPNormalSocket - Socket already created!\n",this);		return false;	// Socket already open!	}			m_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);	m_Protocol = WSSocket::WSSOCK_PROTO_UDP;#ifdef WSCORE_WIN32	if (!m_sock)#endif#ifdef WSCORE_LINUX	if (m_sock==-1)#endif	{		m_pLog->log("WSNormalSocket %x failed to createUDPNormalSocket - Could not create socket!\n",this);		return false;	}	unsigned int packSize;	int sz = sizeof(unsigned int);	WSNet& Net = WSNet::getSingleton();	if (Net.getSysMaxPacketSize()==0)	{		getsockopt(m_sock,SOL_SOCKET,SO_MAX_MSG_SIZE,(char*)&packSize,&sz);			Net.setSysMaxPacketSize(packSize);	};	m_pLog->log("WSNormalSocket %x created socket descriptor %d...\n",this,m_sock);	m_bReady = true;	return true;};
Winterdyne Solutions Ltd is recruiting - this thread for details!
tcp better for data

in addition more reliable

Kuphryn
Quote:The UDP packet size limit depends on the lower levels of the connection (Ethernet, wireless lan, whatever is used to actually transmit your packet), 1 UDP packet has to be delivered in one piece


That's not true. UDP can fragment over multiple IP fragments, and reassemble on the other end. Only if the "don't fragment" bit is set will it be delivered in a single piece.

However, if any one of the fragments don't make it within some time-out, the entire UDP datagram will be discarded on the receiving end, because the entire packet must be reassembled to be delivered -- it's "all or nothing" at the application layer.

Btw: TCP is the right solution for downloading map or patch files that are not part of the real-time data stream, assuming that you're not also trying to run a real-time data stream at the same time. If you're trying to also run the game on the same channel, you'll get in trouble where the TCP packets will cause UDP packet droppage and jitter.
enum Bool { True, False, FileNotFound };
UDP can be a suitable mechanism for deploying files in a very small number of circumstances that probably don't apply to your application if it's anything like a normal game on a PC. For example, TFTP, a file transfer protocol that uses UDP, is used in a number of situations such as updating router firmware on routers without mass storage.

The best programming technique for transfering the file over TCP would depend on your networking API, the use for the file and/or programming language you are using. For example, if you use Java, it may be more suitable to use object serialization rather than raw file data to send the map information.

Additonally, it sounds like you want to transmit your file with a single call with TCP/IP. For most APIs, such as the sockets API, trying to send the entire file in a single send() call would be a mistake since send() may not actually send all the bytes in the buffer. It will return a value that indicates the number of bytes it actually did send. You'll probably need to feed successive chunks of the file with multiple send() calls.
sendfile() will send a full file on a socket in a single call. Each OS has a variation of that call (there's also a WinSock version).

It's pretty much a way of putting a web server mostly into kernel space, for better performance. Some flavors even take iovec style pointers for prepending headers :-)

enum Bool { True, False, FileNotFound };
You may find it more convenient to just send the URL of the resource and use HTTP to transfer the file.

That way you don't need to bother writing the server, you can just use an existing one. There are also lots of client libraries available, one of them is likely to be suitable.

Mark

This topic is closed to new replies.

Advertisement