I created a very UDP simple server (Linux kernel 2.4.20) that listens
on two ports --- 6000 & 7000. I am using select(), but I am seeing
some unexpected behavior. The server seems to get "locked" on to the
port number on which it receives its first message. For example, if
the first message to the server is sent on port 6000, it will receive
all subsequent messages on port 6000, but it will simply ignore all
messages on port 7000. Similarly, if the first message to the server
is sent on port 7000, it will receive all subsequent messages on port
7000, but it will turn deaf to port 6000.
I am sure that there is some careless mistake on my part. Any help
will be appreciated.
Regards,
Song
///// Sample Source Code /////
#include <unistd.h>
#include <ctype.h>
#include <iostream>
#include <time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
#define MAXMESG 2048
#define PORT_1 6000
#define PORT_2 7000
int maxDescriptor_g = 0;
//////////////////////////////////////////////////////////
//
// Simply dumps the message contents in hex
//
//////////////////////////////////////////////////////////
void
printMessage(void *msg, size_t msgLen)
{
ios_base::fmtflags oldFmtSettings = cout.setf(ios::showbase);
char *msgPtr = (char *)msg;
for(size_t i = 0; i < msgLen; i++)
{
if(!(i%10))
cout << endl;
unsigned char ch = *(msgPtr+i);
cout << hex << int(ch) << " ";
}
cout << endl;
cout.setf(oldFmtSettings);
cout <<"\n\n\n";
}
//////////////////////////////////////////////////////////
//
// Processes incoming message
//
//////////////////////////////////////////////////////////
void
processMsg(int sockd)
{
int bytesRead, clilen;
char mesg[MAXMESG];
sockaddr_in from;
size_t addrLen = sizeof(sockaddr_in);
size_t msgLen;
for(;

{
bytesRead = recvfrom(sockd, mesg, MAXMESG, 0,(sockaddr*) &from,
(socklen_t *)&addrLen);
if(bytesRead < 0)
{
cerr << "recvfrom: error" << endl;
continue;
}
cout << "Received following message from " <<
inet_ntoa(from.sin_addr)
<< ":\n";
printMessage(mesg, bytesRead);
break;
}
}
//////////////////////////////////////////////////////////
//
// Makes calls to socket(), bind() etc.
//
//////////////////////////////////////////////////////////
int
registerNewListener(int& sd, unsigned short portNum, fd_set& readSet)
{
sockaddr_in serverDetails;
serverDetails.sin_family = AF_INET;
serverDetails.sin_addr.s_addr = htonl(INADDR_ANY);
serverDetails.sin_port = htons(portNum);
socklen_t serverAddrLen = sizeof(sockaddr_in);
if((sd=socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
cerr << "server: can't open datagram socket" << endl;
return -1;
}
if(bind(sd, (const sockaddr*)&serverDetails, serverAddrLen) < 0)
{
cerr << "server: can't bind local address" << endl;
close(sd);
return -2;
}
int on = 1;
if(ioctl(sd, FIONBIO, &on) < 0)
{
cerr << "server: can't set the socket to non-blocking" << endl;
return -3;
}
FD_SET(sd, &readSet);
if(sd > maxDescriptor_g)
maxDescriptor_g = sd;
return 0;
}
//////////////////////////////////////////////////////////
//
// main
//
//////////////////////////////////////////////////////////
main(int argc, char *argv[])
{
int sockd1, sockd2;
fd_set readFDSet;
FD_ZERO (&readFDSet);
if(registerNewListener(sockd1, PORT_1, readFDSet) < 0)
{
return -1;
}
if(registerNewListener(sockd2, PORT_2, readFDSet) < 0)
{
return -1;
}
for(;

{
int rc;
if((rc = select(maxDescriptor_g+1, &readFDSet, NULL, NULL, NULL)) <
1)
{
cerr << "server: Bad return value from select (" << rc << ")\n";
return -3;
}
if(FD_ISSET(sockd1, &readFDSet))
processMsg(sockd1);
if(FD_ISSET(sockd2, &readFDSet))
processMsg(sockd2);
}
}