// ==========================
// UDP Socket Loopback Sample
// Language: C++
// Microsoft Windows 2000 Professional
// Cygwin 1.5.18
// GNU g++ 3.4.4
// --------------------------
// Version 1.0
// --------------------------
// Source: loopback.cpp
// ==========================
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn
[
loopback.cpp ]
// ==========================
// UDP Socket Loopback Sample
// Language: C++
// Microsoft Windows 2000 Professional
// Cygwin 1.5.18
// GNU g++ 3.4.4
// --------------------------
// Version 1.0
// ==========================
// --------------------
// ---- C-includes ----
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <cassert>
// --------------------
// --------------------
// --- C++-includes ---
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
// --------------------
// --------------------
// --- System calls ---
// ----- includes -----
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
// --------------------
// --------------------
#define IP_ADDRESS "127.0.0.1"
// Ethernet adapter Local Area Connection 2: Terayon Cable Modem (NDIS 5)
// #define IP_ADDRESS "172.XXX.YYY.ZZZ"
// PPP adapter: WAN (PPP/SLIP) Interface
// #define IP_ADDRESS "85.XXX.YYY.ZZZ"
#define PING_PORT 5000
#define PONG_PORT 6000
#define BUF_SIZE 100
#define ACK_PREFIX "ACK: "
#define SEND_PREFIX "REQUEST: "
// --------------------
#define STAMP "[" << __FILE__ << ", " << setw (3) << __LINE__ << "; " << __PRETTY_FUNCTION__ << "] "
#define ERRNO_MSG(x) {ostringstream o_s_s; o_s_s << STAMP << "errno = " << errno << " (" << strerror (errno) << "): " << x << endl; cout << o_s_s.str(); cout.flush(); }
#define ERROR_MSG(x) {ostringstream o_s_s; o_s_s << STAMP << "ERROR -> " << x << endl; cout << o_s_s.str(); cout.flush(); }
#define WARNING_MSG(x) {ostringstream o_s_s; o_s_s << STAMP << "WARNING -> " << x << endl; cout << o_s_s.str(); cout.flush(); }
#define INFO_MSG(x) {ostringstream o_s_s; o_s_s << STAMP << "INFO -> " << x << endl; cout << o_s_s.str(); cout.flush(); }
// --------------------
static void ping ()
{
int sockFd;
sockaddr_in sockAddr;
sockaddr_in toSockAddr;
sockaddr_in fromSockAddr;
char recvBuffer[BUF_SIZE];
char sendBuffer[BUF_SIZE];
int optVal = 1;
int fromLen;
ssize_t actualRecvLen;
ssize_t actualSendLen;
INFO_MSG ("Ping started");
sockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockFd < 0)
{
ERRNO_MSG ("Unable to perform socket()");
return;
}
if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal)) != 0)
{
ERRNO_MSG ("Unable to perform setsockopt()");
return;
}
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
sockAddr.sin_port = htons(PING_PORT);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
ERROR_MSG ("Illegal ip-addr = " << IP_ADDRESS);
if (close (sockFd) != 0)
{
ERRNO_MSG ("Unable to perform close()");
}
return;
}
if (bind(sockFd, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)) != 0)
{
ERRNO_MSG ("Unable to perform bind()");
return;
}
bool forever = true;
INFO_MSG ("Ping before while: ping-ip = " << inet_ntoa (sockAddr.sin_addr) << ", ping-port = " << ntohs (sockAddr.sin_port));
while (forever)
{
// --------------------------
memset(&toSockAddr, 0, sizeof(toSockAddr));
toSockAddr.sin_family = AF_INET;
toSockAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
toSockAddr.sin_port = htons(PONG_PORT);
INFO_MSG ("Ping before sending");
static string str;
static char ch = 'A';
if ((str.size() + sizeof (SEND_PREFIX)) >= sizeof (sendBuffer))
{
str.clear();
}
str += ch;
ch++;
if (ch > 'z')
{
ch = 'A';
}
memset(&sendBuffer[0], 0, sizeof (sendBuffer));
strcpy (sendBuffer, SEND_PREFIX);
strcat (sendBuffer, str.c_str());
actualSendLen = sendto(
sockFd,
sendBuffer,
strlen (sendBuffer),
0,
reinterpret_cast<sockaddr*>(&toSockAddr),
sizeof(toSockAddr)
);
if (actualSendLen != strlen (sendBuffer))
{
WARNING_MSG ("Inconsistent send-len: len-to-be-sent = " << strlen (sendBuffer) << ", actual-sent-len = " << actualSendLen);
}
INFO_MSG ("Ping sent message: to-ip = "
<< inet_ntoa (toSockAddr.sin_addr)
<< ", to-port = "
<< ntohs (toSockAddr.sin_port)
<< "; len = "
<< actualSendLen
<< ", request = \""
<< sendBuffer
<< "\""
);
// ---------------------------------
memset(&sockAddr, 0, sizeof(sockAddr));
fromLen = sizeof (sockAddr);
INFO_MSG ("Ping is waiting for reply");
memset(&recvBuffer[0], 0, sizeof (recvBuffer));
actualRecvLen = recvfrom(
sockFd,
recvBuffer,
sizeof (recvBuffer),
0,
reinterpret_cast<sockaddr*>(&fromSockAddr),
&fromLen
);
if (actualRecvLen < 0)
{
WARNING_MSG ("Unable to perform recvfrom()");
continue;
}
INFO_MSG ("Ping got reply: from-ip = "
<< inet_ntoa (fromSockAddr.sin_addr)
<< ", from-port = "
<< ntohs (fromSockAddr.sin_port)
<< "; len = "
<< actualRecvLen
<< ", reply = \""
<< recvBuffer
<< "\""
);
sleep (2);
} // while (forever)
} // ping()
// --------------------
static void pong ()
{
int sockFd;
sockaddr_in sockAddr;
sockaddr_in toSockAddr;
sockaddr_in fromSockAddr;
char recvBuffer[BUF_SIZE];
char sendBuffer[BUF_SIZE];
int optVal = 1;
int fromLen;
ssize_t actualRecvLen;
ssize_t actualSendLen;
INFO_MSG ("Pong started");
sockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockFd < 0)
{
ERRNO_MSG ("Unable to perform socket()");
return;
}
if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal)) != 0)
{
ERRNO_MSG ("Unable to perform setsockopt()");
return;
}
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
sockAddr.sin_port = htons(PONG_PORT);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
ERROR_MSG ("Illegal ip-addr = " << IP_ADDRESS);
if (close (sockFd) != 0)
{
ERRNO_MSG ("Unable to perform close()");
}
return;
}
if (bind(sockFd, (sockaddr*)&sockAddr, sizeof(sockAddr)) != 0)
{
ERRNO_MSG ("Unable to perform bind()");
return;
}
INFO_MSG ("Pong before while: pong-ip = " << inet_ntoa (sockAddr.sin_addr) << ", pong-port = " << ntohs (sockAddr.sin_port));
bool forever = true;
while (forever)
{
memset(&sockAddr, 0, sizeof(sockAddr));
fromLen = sizeof (sockAddr);
INFO_MSG ("Pong is waiting for request");
memset(&recvBuffer[0], 0, sizeof (recvBuffer));
actualRecvLen = recvfrom(
sockFd,
recvBuffer,
sizeof (recvBuffer),
0,
reinterpret_cast<sockaddr*>(&fromSockAddr),
&fromLen
);
if (actualRecvLen < 0)
{
WARNING_MSG ("Unable to perform recvfrom()");
continue;
}
INFO_MSG ("Pong got request: from-ip = "
<< inet_ntoa (fromSockAddr.sin_addr)
<< ", from-port = "
<< ntohs (fromSockAddr.sin_port)
<< "; len = "
<< actualRecvLen
<< ", request = \""
<< recvBuffer
<< "\""
);
// -------------------------
memset(&toSockAddr, 0, sizeof(toSockAddr));
toSockAddr.sin_family = AF_INET;
toSockAddr.sin_addr.s_addr = fromSockAddr.sin_addr.s_addr;
toSockAddr.sin_port = fromSockAddr.sin_port;
INFO_MSG ("Pong before sending");
memset(&sendBuffer[0], 0, sizeof (sendBuffer));
strcpy (sendBuffer, ACK_PREFIX);
strcat (sendBuffer, recvBuffer);
actualSendLen = sendto(
sockFd,
sendBuffer,
strlen (sendBuffer),
0,
reinterpret_cast<sockaddr*>(&toSockAddr),
sizeof(toSockAddr)
);
if (actualSendLen != strlen (sendBuffer))
{
WARNING_MSG ("Inconsistent send-len: len-to-be-sent = " << strlen (sendBuffer) << ", actual-sent-len = " << actualSendLen);
}
INFO_MSG ("Pong sent reply: to-ip = "
<< inet_ntoa (toSockAddr.sin_addr)
<< ", to-port = "
<< ntohs (toSockAddr.sin_port)
<< "; len = "
<< actualSendLen
<< ", request = \""
<< sendBuffer
<< "\""
);
} // while (forever)
} // pong()
// --------------------
void test1()
{
pthread_t pingThread;
pthread_t pongThread;
errno = pthread_create(&pongThread,
NULL,
reinterpret_cast<void * (*) (void *)> (pong),
NULL
);
if (errno != 0)
{
ERRNO_MSG ("Unable to perform pthread_create() for pongThread");
return;
}
sleep (2);
errno = pthread_create(&pingThread,
NULL,
reinterpret_cast<void * (*) (void *)> (ping),
NULL
);
if (errno != 0)
{
ERRNO_MSG ("Unable to perform pthread_create() for pingThread");
return;
}
while (true)
{
sleep (5);
}
} // test1()
// --------------------
int main()
{
cout << "Hello world from " << __FILE__ << endl; cout.flush();
cout << "IP_ADDRESS = " << IP_ADDRESS << endl; cout.flush();
test1();
cout << "Bye from " << __FILE__ << endl; cout.flush();
return 0;
}