I'm sending multiple UDP datagrams in a cycle and receiving them using sendmmsg
and recvmmsg
system calls. My client-side code is this :
struct mmsghdr *msgs;
struct iovec *iovecs;
while(interval){
msgs = new struct mmsghdr[no_of_packets];
iovecs = new struct iovec[no_of_packets];
for(int i = 0;i < no_of_packets;i++){
memset(&iovecs[i], 0, sizeof(iovecs[i]));
iovecs[i].iov_base = (void *) to_string(i + 1).c_str();
iovecs[i].iov_len = 1;
}
memset(msgs, 0, sizeof(msgs));
for(int i = 0;i < no_of_packets;i++){
msgs[i].msg_hdr.msg_iov = &iovecs[i];
msgs[i].msg_hdr.msg_iovlen = 1;
}
ret_val = sendmmsg(socket_id, msgs, no_of_packets, 0);
no_of_packets++;
if(ret_val == -1)
std::cerr << "Message sending failed.\n";
else
cout << ret_val << " messages sent\n";
sleep(interval--);
}
The client keeps sending messages until interval is positive. And my server side code keeps receiving these messages :
while(true){
msgs = new struct mmsghdr[no_of_packets];
iovecs = new struct iovec[no_of_packets];
char buffers[no_of_packets][packet_size + 1];
memset(msgs, 0, sizeof(msgs));
for(int i = 0;i < no_of_packets;i++){
iovecs[i].iov_base = buffers[i];
iovecs[i].iov_len = packet_size;
msgs[i].msg_hdr.msg_iov = &iovecs[i];
msgs[i].msg_hdr.msg_iovlen = 1;
}
ret_val = recvmmsg(socket_id, msgs, no_of_packets, 0, NULL);
no_of_packets++;
if(ret_val < 0){
break;
}
else{
cout << ret_val << " messages received\n";
for(int i = 0;i < ret_val;i++) {
buffers[i][msgs[i].msg_len] = 0;
printf("Trip %d : %s\n", i + 1, buffers[i]);
}
}
}
The problem is my server doesn't exit from the while
loop even after the client finishes sending all the messages. How can I make the server aware that the message receving has finished ?
UDP servers do not have any concept of a client connection, nor does a UDP server know when a client has "finished sending".
Your
recvmmsg
call is just going to wait until a client sends it a datagram. If there's a scenario where your client can tell the server to exit, it needs to be done at the application protocol level.