Reputation: 566
I am practicing a bit with sockets and UDP client-server architecture and, referring to some examples available on the web, I have implemented a very simple UDP server using C and a UDP client class using C++.
Briefly speaking, the current implementation let the server listen for incoming messages and transmit back the same packet to client.
It seems to work fine if client makes sequential requests.
Here is a brief explanatory example:
#include "UDPClient.h"
int main(int argc, char* argv[]) {
UDPClient testClient;
testClient.initSockets(1501, "127.0.0.1", 1500);
for (int i = 0; i < 10; i++) {
testClient.notifyEntry();
testClient.notifyExit();
}
return 0;
}
Since client actually should share with server more informations at the same time, I tested the same code block starting new threads:
#include <thread>
#include "UDPClient.h"
int main(int argc, char* argv[]) {
UDPClient testClient;
std::thread thrdOne, thrdTwo;
testClient.initSockets(1501, "127.0.0.1", 1500);
for (int i = 0; i < 10; i++) {
thrdOne = std::thread(UDPClient::notifyEntry, std::ref(testClient));
thrdTwo = std::thread(UDPClient::notifyExit, std::ref(testClient));
}
return 0;
}
As you can see, notifyEntry
and notifyExit
have been made static
and currently need a reference to a class instance to work properly.
Furthermore, inside their function body I have added also a little code block in order to check if, since the server sends back the same content, the sent message is equal to the received one.
Here is a explanatory example:
void UDPClient::notifyEntry(UDPClient& inst) {
char buffer = "E"
inst.sendPacket(buffer); // sendto...
inst.receivePacket(buffer); // recvfrom...
if (!(buffer == 'E') ){
std::string e = "Buffer should be E but it is ";
e.append(buffer);
throw UDPClientException(e);
}
}
Using multithreading often happens that the above mentioned check throws exception, because the buffer actually contains another char
(the one sent by notifyExit
).
Taking this information into account, I would like to ask you:
recvfrom
of a thread can catch also the response of a request from another one, being the socket instantiated only a single bound socket?notifyEntry
and one for notifyExit
)? Does multithreading on server for response only not solve the issue mentioned anyway?Upvotes: 0
Views: 1074
Reputation: 73041
this happens because the recvfrom of a thread can catch also the response of a request from another one, being the socket instantiated only a single bound socket?
That's very likely -- if you have multiple threads calling recvfrom()
on the same UDP socket, then it will be indeterminate/unpredictable which thread receives which incoming UDP packet.
if yes, should I instantiate more than a single socket (for instance, each one usable for only a single type of messages, that is one for notifyEntry and one for notifyExit)?
Yes, I'd recommend having each thread create its own private UDP socket and bind() its socket to its own separate port (e.g. by passing 0 as the port number to bind()
); that way each thread can be sure to receive only its own responses and not get confused by responses that were intended for other threads. (Note that you'll also want to code your server to send its replies back to the IP address and port that was reported by the recvfrom()
call, rather than sending reply packets back to a hard-coded port number)
Does multithreading on server for response only not solve the issue mentioned anyway?
No, the correct handling of UDP packets (or not) is a separate issue that is independent of whether the server is single-threaded or multi-threaded.
Upvotes: 1