UDP Confusion c++ sockets

Started by
33 comments, last by hplus0603 5 years, 8 months ago
1 hour ago, _WeirdCat_ said:

Thats exactly what im doing at this point. But will tcp be able to handle this realtime chat?

Interesting.  If you comment-out the communication does the server drawing latency go away?

Advertisement
1 hour ago, _WeirdCat_ said:

But will tcp be able to handle this realtime chat? I doubt

Have you defined what "realtime" means for your application?  What is the benchmark you are trying to achieve?  Also, if you are going to the world with this, there is inherent latency in any communication from (for example) California, USA to Perth, Australia.  Is that part of your benchmark parameters?

Nah its only dedicated for communication up to 3 meters( i want to smoothly edit scene on different devices - this is just something like multiscreen purpose - theyll be working like one app - imagine that you have 4 phones, you have side projection, front projecrion, top projection and 3d projection and you model one object with them). And what about that commenting out the communication? You mean sending and receiving ? Well that is obvious i dont get any lag. :)

2 hours ago, _WeirdCat_ said:

But will tcp be able to handle this realtime chat? I doubt.

Outside of very specific scenarios involving packet loss, TCP is not particularly slow. If the data you are transmitting needs to be ordered (and/or lossless), it's going to take a fair amount of effort to design and build a UDP system that outperforms TCP in the general case.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

3 minutes ago, _WeirdCat_ said:

And what about that commenting out the communication? You mean sending and receiving ? Well that is obvious i dont get any lag.

In that case, you may need to review how you are implementing your commands/queues/locks.  You should be able to draw with a minuscule amount of lag.  With that said, I am assuming that a finger-down, pixel movement (either per-pixel or several pixels in some time snapshot) and finger-up are all discrete events that can be sent on their own (i.e. finger down is sent, then movement is sent, then finger up is sent ~ all individually and not together).

 

5 minutes ago, swiftcoder said:

Outside of very specific scenarios involving packet loss, TCP is not particularly slow. If the data you are transmitting needs to be ordered, it's going to take a fair amount of effort to design and build a UDP system that outperforms TCP in the general case.

Totally agree.

11 hours ago, _WeirdCat_ said:

Thats exactly what im doing at this point. But will tcp be able to handle this realtime chat? I doubt.

Well, unless the link layer is relying on a human morse code operator, TCP should be able to handle the kind of data throughput you're playing with without blinking.

TCP over IP over 802.11n is about 150 megabits per second, divided by the number of devices on your AP.  That means you can send on the order of megabytes every second using TCP.  If you're experiencing delays on the order of seconds to send 20 bytes, the problem is not the underlying network protocol.  Switching to UDP will not alter that fact.

Setting TCP_NODELAY on the TCP channel means the driver won't wait for a full packet to send, which if you're streaming 20 bytes is what you want otherwise you will get, like the name says, delay.

You may want to dump timestamps of operations into a log file and analyse them.  It sounds more like you have inadvertent serialization in your multi-threaded application.  Also, make sure your sockets are read and written in O_NONBLOCK mode.  Your server should be waiting for events and dispatching them to worker threads and never waiting for read or write completion.  You should hold locks only as long as it takes to push or pull data from a queue (and the "data" should be about the size of a pointer or index).

Sequence diagrams are an indispensible tool for analysing flow in this situation. You can even annotate them with expected timings and then match against the actual timings from your log file.

Certainly, blindly fumbling in the dark by switching session protocols on the network is unlikely to get you to where you want to be.

Stephen M. Webb
Professional Free Software Developer

If you think about it, most any game that uses UDP will have some messages that are non-critical (position updates etc) and some that are critical and can't afford to be missed (player dies, player spawns etc). I've always implemented a small system for making sure critical messages come through (and in order), as far as I can remember it took all of 5 mins, this is from memory from 15-20 years ago, something vaguely like this but it should get you started:

  • Critical Message from machine A has an ID which increments by one each time you want to send one,
  • it gets added to a critical send queue. There is a queue pointer which is the ID of the last message that the other machine B has confirmed it has received.
  • Continually send all the messages from the queue pointer to the head of the list.
  • When the other machine B receives a message (or rather up to a certain message) it returns an acknowledgement to A of where it is up to. This can be tagged onto another packet and sent repeatedly.
  • When A receives an acknowledgement, it can get get rid of old messages and move the queue pointer on.

TCP probably does a whole lot of other stuff to keep a good stream for bigger files, but this is not typically necessary, and is more likely to be a hindrance than help unless you are sending files.

"So how would i do that to ensure that when i send hello_set_id(10); the client receives full text, i was thinking of adding a number after each char to ensure that text wont be fragmented like h0e1l2l3o4_5 etc."

You don't have to do that when using UDP protocol because you are sending Datagram messages; meaning you will received the whole message or NOT. When the recipient received it your are guaranteed it's the whole message.

"Hello world"

Unlike when using TCP which is Stream oriented you may received the message in PART or in WHOLE message but guaranteed it will arrived at the other end and in order.

"Hell"
"o"
" world"

Anyway despite post above, can someone explain to me why write fails on nonblocking socket set by fcntl() func

I get errno 32 which means EPIPE

 

Do i have to do maybe some additional things rather than just use write?

 

Code looks like that


const int max_write_fails = 18;


inline int SendStrToFd(unsigned char * pdata, int cmdlen, int sockfd)
{
	bool sentall = false;

	int count = 0;
	int iteration = 0;
	int fails = 0;
	int len_to_write = cmdlen;
	while (!sentall)
	{
		iteration++;
		if (count >= cmdlen) break;
		if (iteration > 1500) break;
		if (len_to_write <= 0) break; //we shouldnt even be here but ill add log exception
		int wb = write(sockfd, &pdata[ count ], size_t( len_to_write ));
		if (wb < 0) 
		{
			fails = fails + 1;
			if (fails >= max_write_fails)
		break;
		}
		if (wb >= 0)
		{
		count = count + wb;
		len_to_write = len_to_write - wb;
		}
		if (count >= cmdlen) { sentall = true; break; }
	}
	if ( sentall ) return 1; else return -1;
}

inline int SendStrToFd(AnsiString txt, int sockfd)
{
	int cmdlen = TextLength( txt );
unsigned char * pdata = new unsigned char[ cmdlen ];
for (int i=0; i < cmdlen; i++)
pdata[i] = ( unsigned char )txt[i];

int result = SendStrToFd(pdata, cmdlen, sockfd);
if (result < 0) ALOG("send error: "+errno2str());
delete [] pdata;
return result;
}

I just keep getting -1 on first write and so on

1 hour ago, _WeirdCat_ said:

I get errno 32 which means EPIPE

EPIPE typically means that the other end closed the connection. Are you sure both ends of this equation are working correctly?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement