C++ UDP. Why is recvfrom() is not blocking? - c++

I am writing some simple client/server code using UDP. The program works fine, but if I only start the client, the recvfrom method does not block. However, when I remove the sendto method, recvfrom starts to block. Any idea of what is going on?
Here is the client side code:
int server_length; /* Length of server struct */
char send_buffer[256] = "hi"; /* Data to send */
time_t current_time; /* Time received */
while(true)
{
/* Tranmsit data to get time */
server_length = sizeof(struct sockaddr_in);
if (sendto(m_oSocket, send_buffer, (int)strlen(send_buffer) + 1, 0, (struct sockaddr *)&m_oServer, server_length) == -1)
{
fprintf(stderr, "Error transmitting data.\n");
continue;
}
/* Receive time */
if (recvfrom(m_oSocket, (char *)&current_time, (int)sizeof(current_time), 0, (struct sockaddr *)&m_oServer, &server_length) < 0)
{
fprintf(stderr, "Error receiving data.\n");
continue;
}
/* Display time */
printf("Current time: %s\n", ctime(&current_time));
Sleep(1000);
}
And here is the initialization:
unsigned short m_iPortnumber;
struct sockaddr_in m_oServer;
struct sockaddr_in m_oClient;
SOCKET m_oSocket;
WSADATA w; /* Used to open Windows connection */
int a1, a2, a3, a4; /* Server address components in xxx.xxx.xxx.xxx form */
a1 = 192;
a2 = 168;
a3 = 2;
a4 = 14;
m_iPortnumber = 52685;
/* Open windows connection */
if (WSAStartup(0x0101, &w) != 0)
{
fprintf(stderr, "Could not open Windows connection.\n");
exit(0);
}
/* Open a datagram socket */
m_oSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (m_oSocket == INVALID_SOCKET)
{
fprintf(stderr, "Could not create socket.\n");
WSACleanup();
exit(0);
}
/* Clear out server struct */
memset((void *)&m_oServer, '\0', sizeof(struct sockaddr_in));
/* Set family and port */
m_oServer.sin_family = AF_INET;
m_oServer.sin_port = htons(m_iPortnumber);
/* Set server address */
m_oServer.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)a1;
m_oServer.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)a2;
m_oServer.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)a3;
m_oServer.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)a4;
/* Clear out client struct */
memset((void *)&m_oClient, '\0', sizeof(struct sockaddr_in));
/* Set family and port */
m_oClient.sin_family = AF_INET;
m_oClient.sin_addr.s_addr=INADDR_ANY;
m_oClient.sin_port = htons(0);
/* Bind local address to socket */
if (bind(m_oSocket, (struct sockaddr *)&m_oClient, sizeof(struct sockaddr_in)) == -1)
{
fprintf(stderr, "Cannot bind address to socket.\n");
closesocket(m_oSocket);
WSACleanup();
exit(0);
}

There are a variety of ways that sendto can fail. Some, such as arp failure, will cause an error during sendto. Other, such as ICMP port unreachable, may be reported when you next use the socket.
Your recvfrom call could actually be fetching the ICMP packet sent in response to your outgoing packet.
Does a second recvfrom block as expected?

Socket required to be set BLOCKING/NON-BLOCKING.
Set BLOCKING
int nMode = 0; // 0: BLOCKING
if (ioctlsocket (objSocket, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(SendingSocket);
WSACleanup();
return iRet;
}
Set NON-BLOCKING
int nMode = 1; // 1: NON-BLOCKING
if (ioctlsocket (objSocket, FIONBIO, &nMode) == SOCKET_ERROR)
{
closesocket(SendingSocket);
WSACleanup();
return iRet;
}

It looks like you're setting up the server socket and the client socket the same way. The initialization looks good for a server, but for the client, you'll want to bind to port 0.
In fact, for both of them you can do INADDR_ANY (IP 0.0.0.0), which doesn't bind to a specific interface, but instead allows any connection on the correct port.

Related

Waiting on sockets using the function WaitForMultipleObjects (msdn)

I am trying to implement a unit test to see if using the function "WaitForMultipleObjects" works properly with socket. To do so I implemented a simple UDP server-client protocol. The server bind his socket and wait to receive data from receiver using the function "WaitForMultipleObjects". Once the server receives data from the client, it displays it then waits 5 seconds. The problem here that if the client try to send 2 messages during this five seconds, the first one is displayed while the second one will block the function "WaitForMultipleObjects" forever. I know that I can use the "Select" function to do that since the socket is the only object I am waiting for, but it's just a unit test. In my real project I need to wait on a socket and another object's type which is a windows event (which is of type HANDLE) at the same time. And that's why i am trying to use "WaitForMultipleObjects" on sockets.
Here's the server code:
/*
Simple UDP Server
*/
#include<winsock2.h>
#include<windows.h>
#include <ws2tcpip.h>
#include<stdio.h>
#include<iostream>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to listen for incoming data
int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;
HANDLE SEvent;
slen = sizeof(si_other) ;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( PORT );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
SEvent = WSACreateEvent();
WSAEventSelect( s, SEvent, FD_READ);
//keep listening for data
while(1)
{
printf("Waiting for data...");
fflush(stdout);
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
INT r = WaitForMultipleObjectsEx(1,&SEvent,FALSE,INFINITE,TRUE);
if( r == WAIT_OBJECT_0)
{
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("Data: %s\n" , buf);
//now reply the client with the same data
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
ResetEvent(SEvent);
Sleep(5000);
}
else
{
std::cerr<<"WaitForMultipleObject() Error ( "<<GetLastError()<<" )"<<std::endl;
exit(0);
}
}
closesocket(s);
WSACleanup();
return 0;
}
Here's the client code:
/*
Simple udp client
*/
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define SERVER "127.0.0.1" //ip address of udp server
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to listen for incoming data
int main(void)
{
struct sockaddr_in si_other;
int s, slen=sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];
WSADATA wsa;
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//create socket
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//setup address structure
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
//start communication
while(1)
{
printf("Enter message : ");
gets(message);
//send the message
if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//receive a reply and print it
//clear the buffer by filling null, it might have previously received data
/*memset(buf,'\0', BUFLEN);
//try to receive some data, this is a blocking call
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts(buf);*/
}
closesocket(s);
WSACleanup();
return 0;
}
Note: I didn't write all the code. I used a code that was already written (from the internet) but made some changes.
Does anyone know how to fix this problem? (using "WaitForMultipleObjects" on socket properly)
The problem here that if the client try to send 2 messages during this five seconds, the first one is displayed while the second one will clock the function "WaitForMultipleObjects" forever.
Your server code has a race condition.
Your should call WSAResetEvent/ResetEvent before calling recvfrom, not afterwards. Otherwise, there is a possiblity that new data will arrive between the call to recvfrom and WSAResetEvent, setting the event object to signalled. In that case, WSAResetEvent will set the event back to non-signalled, causing you to lose the notification of new data being available.
Also, according to the documentation of WSAEventSelect, after reading data from a socket, if more data is available to be read, the event will automatically be set to signalled again, in order to indicate that more data is available. If you call WSAResetEvent afterwards, then you will set the event back to non-signalled, causing you to lose the notification of new data being available. This is probably the reason for the behavior you describe in the question.
You should rather call WSAResetEvent/ResetEvent immediately after WSAWaitForMultipleEvents/WaitForMultipleObjectsEx. See the documentation for the function WSAWaitForMultipleEvents for a code example (that example uses overlapped I/O instead of WSAEventSelect, though).

C/C++: socket() creation fails in the loop, too many open files

I am implementing a client-server TCP socket application. Client is on an OpenWRT Linux router (C based) and writes some data on the socket repeatedly and in a loop at some frequency rate. The Server is on a Linux Ubuntu machine (C/C++ based) and reads data in a loop according to data arrival speed.
Problem: Running the Server and then Client, server keeps reading new data. Both sides work well until the number of data deliveries (# of connections) reaches 1013. After that, the Client stuck at socket(AF_INET,SOCK_STREAM,0) with socket creation failed...: Too many open files. Apparently, the number of open fd approaches ulimit -n = 1024 on client.
I put the snippets of the code which shows the loop structures for Server.cpp and Client.c:
Server.c:
// TCP Socket creation stuff over here (work as they should):
// int sock_ = socket() / bind() / listen()
while (1)
{
socklen_t sizeOfserv_addr = sizeof(serv_addr_);
fd_set set;
struct timeval timeout;
int connfd_;
FD_ZERO(&set);
FD_SET(sock_, &set);
timeout.tv_sec = 10;
timeout.tv_usec = 0;
int rv_ = select(sock_ + 1, &set, NULL, NULL, &timeout);
if(rv_ == -1){
perror("select");
return 1;
}
else if(rv_ == 0){
printf("Client disconnected.."); /* a timeout occured */
close (connfd_);
close (sock_);
}
else{
connfd_ = accept (sock_,(struct sockaddr*)&serv_addr_,(socklen_t*)&sizeOfserv_addr);
if (connfd_ >= 0) {
int ret = read (connfd_, &payload, sizeof(payload)); /* some payload */
if (ret > 0)
printf("Received %d bytes !\n", ret);
close (connfd_); /* Keep parent socket open (sock_) */
}else{
printf("Server acccept failed..\n");
close (connfd_);
close (stcp.sock_);
return 0;
}
}
}
Client.cpp:
while (payload_exist) /* assuming payload_exist is true */
{
struct sockaddr_in servaddr;
int sock;
if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
perror("socket creation failed...\n");
int one = 1;
int idletime = 2;
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idletime, sizeof(idletime));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.100.12");
servaddr.sin_port = htons(PORT); /* some PORT */
if (connect (sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0){
perror("connect failed...");
return 1;
}
write(sock, (struct sockaddr*)&payload, sizeof(payload)); /* some new payload */
shutdown(sock,SHUT_WR);
bool serverOff = false;
while (!serverOff){
if(read(sock, &res, sizeof(res)) < 0){
serverOff = true;
close(sock);
}
}
}
NOTE: payload is 800 bytes and always gets fully transmitted per one write action. Having both codes defined under int main(), the client keeps creating sockets and sending data, on the other side, server receives all and would automatically close() and leave if client terminates, due to using select(). If I don't terminate the Client, however, by checking some print logs, it is evident that Server successfully receives 1013 payloads before client crashes with socket creation failed...: Too many open files.
Update:
Following the point mentioned by Steffen Ullrich, it turned out that, the client socket fd has no leak, and the existence of a second fd in the original loop (which was left open) was making the ulimit exceed the limit.
if(read(sock, &res, sizeof(res)) < 0){
serverOff = true;
close(sock); /********* Not actually closing sock *********/
}
Your check for end of connection is wrong.
read returns 0 if the other side has shut down the connection and <0 only on error.
if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
perror("socket creation failed...\n");
Given the precedence of operators in C this basically says:
sock = ( socket(AF_INET, SOCK_STREAM, 0) == -1) )
if (sock) ...
Assuming that socket(...) will not return an error but a file descriptor (i.e. >=0) the comparison will be false and thus this essentially says sock = 0 while leaking a file descriptor if the fd returned by socket was >0.

C++ How can i join to a multicast mpeg stream?

How can i manage to join a multicast mpeg stream group with an address of udp://#224.1.50.15:1234? What i want to manage is just to make a connection with the stream server to make the server become aware of that i am interested in this multicast group to make the server to send me the stream packets for a period of a time.
For an example:
I am not receiving any packets from this multicast group until i establish a connection to the group with VLC Player. Even after i close the VLC Player i keep receiving packets from the group for a short period of time. What i am trying to do is to receive the packets without the help of VLC Player or any other third party application.
How can i manage to make a connection with this group for the purpose above. If it is even possible?
P.S: I have 4 network interfaces installed.
Thank you!
As the recommendation of Zaboj Campula in his answer in this page; i changed the code as below. Which gives me an error 10093.
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
SOCKET s;
SOCKADDR_IN localif;
struct ip_mreq mreq;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
localif.sin_family = AF_INET;
localif.sin_port = htons(1234);
localif.sin_addr.s_addr = INADDR_ANY;
bind(s, (SOCKADDR *)&localif, sizeof(localif));
mreq.imr_interface.s_addr = INADDR_ANY; //Writing here my local ip didn't change the result.
mreq.imr_multiaddr.s_addr = inet_addr("224.1.50.15");
int rc = NO_ERROR;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Join the group
rc = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
if (rc == SOCKET_ERROR)
{
printf("JoinMulticastGroup: setsockopt failed with error code %d\n", WSAGetLastError());
}
else
{
printf("Joined group: ");
//PrintAddress(group->ai_addr, group->ai_addrlen);
printf("\n");
}
UDP sockets do not support connections. It is not possible to call listen and accept on an UDP socket. You can directly read from the UDP socket when it is bound to a local port.
The socket option IP_ADD_MEMBERSHIP joins the socket to a multicast group.
struct ip_mreq m;
m.imr_interface.s_addr = inet_addr(loca_ip_address);
m.imr_multiaddr.s_addr = inet_addr("224.1.50.15");
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&m, sizeof(m));
You ca find a full example at http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancedmulticast9a.html
Ok, I managed to resolve my issue with the help of the book
Multicast Sockets Practical Guide for Programmers which is written by
David Makofske & Kevin Almeroth
Thank's goes to the writers and Zaboj Campula for their efforts.
I hope this post and the answer will help many others in the future.
The working code is written below!
Compiled with Visual Studio 2017 RC (Console Empty C project)
int sock; /* socket descriptor */
int flag_on = 1; /* socket option flag */
struct sockaddr_in mc_addr; /* socket address structure */
char recv_str[MAX_LEN + 1]; /* buffer to receive string */
int recv_len; /* length of string received */
struct ip_mreq mc_req; /* multicast request structure */
char* mc_addr_str; /* multicast IP address */
unsigned short mc_port; /* multicast port */
struct sockaddr_in from_addr; /* packet source */
unsigned int from_len; /* source addr length */
WSADATA wsaData; /* Windows socket DLL structure */
mc_addr_str = "224.1.50.15"; /* arg 1: multicast ip address */
mc_port = atoi("1234"); /* arg 2: multicast port number */
/* validate the port range */
if ((mc_port < MIN_PORT) || (mc_port > MAX_PORT)) {
fprintf(stderr, "Invalid port number argument %d.\n",
mc_port);
fprintf(stderr, "Valid range is between %d and %d.\n",
MIN_PORT, MAX_PORT);
exit(1);
}
/* Load Winsock 2.0 DLL */
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
fprintf(stderr, "WSAStartup() failed");
exit(1);
}
/* create socket to join multicast group on */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("socket() failed");
exit(1);
}
/* set reuse port to on to allow multiple binds per host */
if ((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&flag_on,
sizeof(flag_on))) < 0) {
perror("setsockopt() failed");
exit(1);
}
/* construct a multicast address structure */
memset(&mc_addr, 0, sizeof(mc_addr));
mc_addr.sin_family = AF_INET;
mc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
mc_addr.sin_port = htons(mc_port);
/* bind to multicast address to socket */
if ((bind(sock, (struct sockaddr *) &mc_addr,
sizeof(mc_addr))) < 0) {
perror("bind() failed");
exit(1);
}
/* construct an IGMP join request structure */
mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
mc_req.imr_interface.s_addr = htonl(INADDR_ANY);
/* send an ADD MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char*)&mc_req, sizeof(mc_req))) < 0) {
perror("setsockopt() failed");
exit(1);
}
for (;;) { /* loop forever */
/* clear the receive buffers & structs */
memset(recv_str, 0, sizeof(recv_str));
from_len = sizeof(from_addr);
memset(&from_addr, 0, from_len);
/* block waiting to receive a packet */
if ((recv_len = recvfrom(sock, recv_str, MAX_LEN, 0,
(struct sockaddr*)&from_addr, &from_len)) < 0) {
perror("recvfrom() failed");
exit(1);
}
/* output received string */
printf("Received %d bytes from %s: ", recv_len,
inet_ntoa(from_addr.sin_addr));
printf("%s", recv_str);
}
/* send a DROP MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(void*)&mc_req, sizeof(mc_req))) < 0) {
perror("setsockopt() failed");
exit(1);
}
closesocket(sock);
WSACleanup(); /* Cleanup Winsock */

My program doesn't send message or doesn't receive to socket, the ip is 127.0.0.1

when I use sockets the program server process doesn't receive any message from the client process/class.
The input port to the user is 5555, but when the program exits the Client's constructor, the port number of sin doesn't match (I think it's because of htons), same goes to the ip address.
please help me fix this.
this is my server code:
#include "SocketUDP.h"
/*
* class constructor
*/
SocketUDP::SocketUDP() {
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
perror("error creating socket");
}
/*
* class destructor
*/
SocketUDP::~SocketUDP() {
close(sock);
}
/*
* this function recieves a message from client/server
* #param - the length of the message
*/
std::string SocketUDP::RecieveMessage(){
unsigned int from_len = sizeof(struct sockaddr_in);
char buffer[4096];
memset(&buffer, 0, sizeof(buffer));
int bytes = recvfrom(sock, buffer, sizeof(buffer), 0,
(struct sockaddr *) &from, &from_len);
if (bytes < 0)
perror("error reading from socket");
return std::string(buffer);
}
This is the client:
#include "UDPClient.h"
/*
* class constructor
*/
UDPClient::UDPClient(char * ip, int port) {
memset(&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
}
/*
* class destructor
*/
UDPClient::~UDPClient() {
// TODO Auto-generated destructor stub
}
/*
* this function sends a message to the client/server
* #param - the message
*/
int UDPClient::SendMessage(std::string st){
int sent_bytes = sendto(sock, st.c_str(), st.length(), 0,
(struct sockaddr *) &sin, sizeof(sin));
if (sent_bytes < 0)
perror("error writing to socket");
return sent_bytes;
}
You are missing a call to bind() in the server. This is where you tell the OS on which port (5555) it should listen for incoming UDP packets.
It is quite confusing if you omit bind()in the server. In this case the OS selects a random port to receive from, which is usually not what one wants.
The class name UDPSocket indicates that this is just a wrapper around a UDP socket, and not a server. A server would have a bind() call in addition, and an endless loop where it processes requests. Perhaps you omitted the server code by accident?

Getting "Transport endpoint is not connected" in UDP socket programming in C++

I am getting Transport endpoint is not connected error in UDP server program, while I am try to
shutdown the socket via shutdown(m_ReceiveSocketId, SHUT_RDWR);
Following is my code snippet:
bool UDPSocket::receiveMessage()
{
struct sockaddr_in serverAddr; //Information about the server
struct hostent *hostp; // Information about this device
char buffer[BUFFERSIZE]; // Buffer to store incoming message
int serverlen; // to store server address length
//Open a datagram Socket
if((m_ReceiveSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
Utility_SingleTon::printLog(LOG_ERROR,"(%s %s %d) UDP Client - socket() error",__FILE__,__func__, __LINE__);
pthread_exit(NULL);
return false;
}
//Configure Server Address.
//set family and port
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(m_ListeningPort);
if (bind(m_ReceiveSocketId, (struct sockaddr *) &serverAddr,sizeof(struct sockaddr_in)) < 0 )
{
Utility_SingleTon::printLog(LOG_ERROR,"(%s %s %d) UDP Client- Socket Bind error=%s",__FILE__,__func__, __LINE__,strerror(errno));
pthread_exit(NULL);
return false;
}
//TODO Re-Route Mechanism.
if((serverAddr.sin_addr.s_addr = inet_addr(m_ServerIPStr.c_str())) == (unsigned long)INADDR_NONE)
{
/* Use the gethostbyname() function to retrieve */
/* the address of the host server if the system */
/* passed the host name of the server as a parameter. */
/************************************************/
/* get server address */
hostp = gethostbyname(m_ServerIPStr.c_str());
if(hostp == (struct hostent *)NULL)
{
/* h_errno is usually defined */
/* in netdb.h */
Utility_SingleTon::printLog(LOG_ERROR,"%s %d %s %s %d", "Host Not found", h_errno,__FILE__,__func__, __LINE__);
pthread_exit(NULL);
return false;
}
memcpy(&serverAddr.sin_addr, hostp->h_addr, sizeof(serverAddr.sin_addr));
}
serverlen = (int )sizeof(serverAddr);
// Loop and listen for incoming message
while(m_RecevieFlag)
{
int receivedByte = 0;
memset(buffer, 0, BUFFERSIZE);
//receive data from the server
receivedByte = recvfrom(m_ReceiveSocketId, buffer, BUFFERSIZE, 0, (struct sockaddr *)&serverAddr, (socklen_t*)&serverlen);
if(receivedByte == -1)
{
Utility_SingleTon::printLog(LOG_ERROR,"[%s:%d#%s] UDP Client - receive error",__FILE__,__LINE__,__func__);
close(m_ReceiveSocketId);
pthread_exit(NULL);
return false;
}
else if(receivedByte > 0)
{
string rMesg;
rMesg.erase();
for(int loop = 0; loop < receivedByte; loop++)
rMesg.append(1, buffer[loop]);
Utility_SingleTon::printLog(LOG_DEBUG,"[%s:%d#%s] received message=%d",__FILE__,__LINE__,__func__, rMesg.length());
QOMManager_SingleTon::getInstance()->setReceivedMessage(rMesg);
raise(SIGUSR1);
}
}
close(m_ReceiveSocketId);
pthread_exit(NULL);
return true;
}
Any help would be appreciated.
Thanks Yuvi.
You don't need to call shutdown() for a UDP socket. From the man page:
The shutdown() call causes all or part of a full-duplex connection on the socket
associated with sockfd to be shut down.
If you call shutdown() on a UDP socket, it will return ENOTCONN
(The specified socket is not connected) because UDP is a connectionless protocol.
All you need to do is close the socket and set the socket to INVALID_SOCKET. Then in your destructor check whether the socket has already been set to INVALID_SOCKET before closing it.