ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
/*
* Based on:
* http://www.gnu.org/software/libc/manual/html_mono/libc.html#Server%20Example
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <syslog.h>
#include <stdarg.h>
#include <time.h>
#define PORT 1730 /* default port to listen on */
#define MAXMSG 10240
#define MAX_QUEUED_CONNS 5
#define MAX_SOCK_IDLE 10 /* minutes */
#define SECS_PER_MIN 60
/*
* Global vars.
*/
static const char gVersion[] = "@(#) tcpechoserver v1.4 " __DATE__;
const char gScaryMsg[] =
"\r\n\r\n OK\r\n"
" Your IP address has been logged: ";
const char gDiscMsg[] = "\r\nDisconnecting due to inactivity\r\n";
char gHostNameBuf[512];
struct sockaddr_in gServerName;
int gMaxFd;
int gNumberClients;
int gDebug;
int gTcpListenSock;
int gUdpSock;
time_t gMaxSockIdle = MAX_SOCK_IDLE * SECS_PER_MIN;
time_t gSockTime[FD_SETSIZE];
fd_set gActive_fd_set;
#ifdef __CYGWIN__
/* Set default log file name for Cygwin build. */
char gLogFilename[FILENAME_MAX] = { "C:/TEMP/tcpecho.log" };
#define SYSLOG mySyslog
/* ------------------------------------------------
* mySyslog
* ------------------------------------------------
*/
static void mySyslog (int level, const char *fmt, ...)
{
static FILE *logFile = NULL;
va_list ap;
char buf[1024];
time_t logTime;
if (logFile == NULL)
{
logFile = fopen (gLogFilename, "a");
}
if (logFile != NULL)
{
va_start (ap, fmt);
vsnprintf (buf, sizeof buf, fmt, ap);
va_end (ap);
logTime = time (NULL);
fprintf (logFile, "%24.24s: %s\n", ctime (&logTime), buf);
fflush (logFile);
}
}
#else
#define SYSLOG syslog
#endif
/* ------------------------------------------------
* getRemoteHostname
* ------------------------------------------------
*/
const char * getRemoteHostname (struct sockaddr_in sin)
{
struct hostent *hp;
hp = gethostbyaddr ((char *) &sin.sin_addr,
sizeof sin.sin_addr, AF_INET);
if (hp)
{
/*
* We found a corresponding hostname, format the string one way...
*/
snprintf (gHostNameBuf, sizeof gHostNameBuf, "%s [%s]", hp->h_name,
inet_ntoa (sin.sin_addr));
}
else
{
/*
* This host not in the host tables or Domain Name Server.
*/
snprintf (gHostNameBuf, sizeof gHostNameBuf, "[%s]",
inet_ntoa (sin.sin_addr));
}
return gHostNameBuf;
}
/* ------------------------------------------------
* bindToPort
* ------------------------------------------------
*/
int bindToPort (int sockStyle)
{
int sock;
int opt;
/* Create the socket. */
sock = socket (PF_INET, sockStyle, 0);
if (sock < 0)
{
SYSLOG (LOG_USER, "socket failed");
exit (EXIT_FAILURE);
}
/*
* Set the "REUSEADDR" option on this socket. This will allow us to
* bind() to it EVEN if there already connections in progress on this
* port number. Otherwise, we would get an "Address already in use"
* error.
*/
if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
{
SYSLOG (LOG_USER, "setsockopt failed");
exit (EXIT_FAILURE);
}
if (bind (sock, (struct sockaddr *) &gServerName, sizeof gServerName) < 0)
{
SYSLOG (LOG_USER, "bind failed");
exit (EXIT_FAILURE);
}
return sock;
}
/* ------------------------------------------------
* closeSock
* ------------------------------------------------
*/
void closeSock (int sock)
{
SYSLOG (LOG_USER, "connection %d: disconnecting.", sock);
close (sock);
FD_CLR (sock, &gActive_fd_set);
gNumberClients--;
}
/* ------------------------------------------------
* echoTcp
* ------------------------------------------------
*/
int echoTcp (int sock)
{
int nbytes;
char buffer[MAXMSG];
char *message="OK\n\r";
nbytes = read (sock, buffer, MAXMSG);
if (nbytes > 0)
{
/* Echo data read and log the time. */
write (sock, message, nbytes);
gSockTime[sock] = time(NULL);
return nbytes;
}
else
{
/* End-of-file or error. */
closeSock (sock);
return -1;
}
}
/* ------------------------------------------------
* echoUdp
* ------------------------------------------------
*/
void echoUdp (int sock)
{
int nbytes;
int size;
struct sockaddr_in sin;
char buffer[MAXMSG];
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = gServerName.sin_port;
size = sizeof sin;
nbytes = recvfrom (sock, buffer, MAXMSG, 0,
(struct sockaddr *) &sin, &size);
if (nbytes < 0)
{
SYSLOG (LOG_USER, "recfrom failed");
return;
}
/* Log the message. */
if (gDebug)
{
SYSLOG (LOG_USER, "Rcvd UDP (%d bytes) from: [%s] Port: %d",
nbytes, inet_ntoa (sin.sin_addr), ntohs(sin.sin_port));
}
/*
* If the source port is 0, we can't send the message back.
*/
if ( ntohs(sin.sin_port) != 0 )
{
/* Echo the message back to the sender. */
nbytes = sendto (sock, buffer, nbytes, 0,
(struct sockaddr *) &sin, size);
if (nbytes < 0)
{
SYSLOG (LOG_USER, "sendto failed");
return;
}
}
}
/* ------------------------------------------------
* checkIdleSockets
* ------------------------------------------------
*/
void checkIdleSockets ( void )
{
int sock;
time_t currentTime = time(NULL);
//if (gDebug) SYSLOG(LOG_USER, "checkIdleSockets");
/*
* Check for an active socket that has been idle
* for longer than gMaxSockIdle seconds.
*/
for (sock = 0; sock <= gMaxFd; ++sock)
{
if (FD_ISSET (sock, &gActive_fd_set) &&
((currentTime - gSockTime[sock]) > gMaxSockIdle ) &&
(sock != gTcpListenSock) &&
(sock != gUdpSock))
{
write (sock, gDiscMsg, sizeof gDiscMsg);
closeSock (sock);
}
}
}
/* ------------------------------------------------
* acceptNewSock
* ------------------------------------------------
*/
void acceptNewSock ( void )
{
struct sockaddr_in clientName;
int acceptSock;
int size;
char buffer[MAXMSG];
/* Accept new connection request on original socket. */
size = sizeof clientName;
acceptSock = accept (gTcpListenSock,
(struct sockaddr *) &clientName,
&size);
if (acceptSock < 0)
{
SYSLOG (LOG_USER, "accept failed");
exit (EXIT_FAILURE);
}
SYSLOG (LOG_USER,
"connection %d from %s, port %hu.",
acceptSock,
getRemoteHostname (clientName),
ntohs (clientName.sin_port));
snprintf(buffer, sizeof buffer, "%s%s\r\n\r\n",
gScaryMsg, gHostNameBuf);
write (acceptSock, buffer, strlen(buffer));
/*
* Add newly accepted socket to the active set.
*/
FD_SET (acceptSock, &gActive_fd_set);
gMaxFd = MAX(gMaxFd, acceptSock);
gSockTime[acceptSock] = time(NULL);
gNumberClients++;
}
/* ------------------------------------------------
* processSockets
* ------------------------------------------------
*/
void processSockets (fd_set *pRead_fd_set)
{
int activeSock;
/* Service all the sockets with input pending. */
for (activeSock = 0; activeSock <= gMaxFd; ++activeSock)
{
if (FD_ISSET (activeSock, pRead_fd_set))
{
if (activeSock == gTcpListenSock)
{
/*
* Accept a connection for a TCP socket.
*/
acceptNewSock ();
}
else if (activeSock == gUdpSock)
{
/*
* Echo data arriving on the UDP socket.
*/
echoUdp (activeSock);
}
else
{
/*
* Echo data arriving on a connected TCP socket.
*/
echoTcp (activeSock);
} /* if (activeSock == gTcpListenSock) */
} /* if (FD_ISSET (activeSock, pRead_fd_set)) */
} /* for (activeSock = 0; ...) */
}
/* ------------------------------------------------
* mainLoop
* ------------------------------------------------
*/
void mainLoop (void)
{
int selectResult;
fd_set read_fd_set;
struct timeval selectTimeout;
struct timeval *pSelectTimeout;
/* Create the tcp socket and set it up to accept connections. */
gTcpListenSock = bindToPort (SOCK_STREAM);
if (listen (gTcpListenSock, MAX_QUEUED_CONNS) < 0)
{
SYSLOG (LOG_USER, "listen failed");
exit (EXIT_FAILURE);
}
gUdpSock = bindToPort (SOCK_DGRAM);
/* Initialize the set of active sockets. */
FD_ZERO (&gActive_fd_set);
FD_SET (gTcpListenSock, &gActive_fd_set);
FD_SET (gUdpSock, &gActive_fd_set);
gMaxFd = MAX(gTcpListenSock, gUdpSock);
gNumberClients = 0;
while (1)
{
if ((gMaxSockIdle > 0) && (gNumberClients > 0))
{
/*
* If there are any clients connected, we'll have
* select timeout every so often so that we can
* check for idle sockets and close them if they
* have been idle too long.
*/
selectTimeout.tv_usec = 0;
selectTimeout.tv_sec = 61;
pSelectTimeout = &selectTimeout;
}
else
{
/*
* If there are no clients, or the timeout is disabled,
* we let select block until there is activity on the
* listen socket.
*/
pSelectTimeout = NULL;
}
read_fd_set = gActive_fd_set;
/* Block until input arrives on one or more active sockets. */
selectResult = select (gMaxFd+1, &read_fd_set, NULL, NULL, pSelectTimeout);
if (selectResult < 0)
{
SYSLOG (LOG_USER, "select failed");
exit (EXIT_FAILURE);
}
if (selectResult > 0)
{
processSockets (&read_fd_set);
}
if ((gMaxSockIdle > 0) && (selectResult >= 0))
{
/*
* Data received or select timed out.
*/
checkIdleSockets ();
}
} /* while (1) */
/* not reached */
}
/* ------------------------------------------------
* usage
* ------------------------------------------------
*/
void usage (const char *progname)
{
fprintf (stderr, "%s\n", gVersion);
#ifdef __CYGWIN__
fprintf (stderr, "\nusage: %s [-adhlpt]\n", progname);
#else
fprintf (stderr, "\nusage: %s [-adhpt]\n", progname);
#endif
fprintf (stderr, " -a <inetaddr> set local address for bind\n");
fprintf (stderr, " -d enable debug logging\n");
fprintf (stderr, " -h print this help\n");
#ifdef __CYGWIN__
fprintf (stderr, " -l <logfile> log to file <logfile> (default: %s)\n",
gLogFilename);
#endif
fprintf (stderr, " -p # set port for bind (default: %d)\n", PORT);
fprintf (stderr, " -t # "
"set idle socket timeout in minutes (default: %d)\n"
" zero disables timeout\n\n",
MAX_SOCK_IDLE);
}
/* ------------------------------------------------
* main
* ------------------------------------------------
*/
int main (int argc, char *argv[])
{
char ch;
char *progname;
int i;
char cmdLine[256];
int cmdIdx;
/*
* Trim path from program name.
*/
progname = rindex (argv[0], '/');
if (progname == NULL)
{
progname = argv[0];
}
else
{
progname++;
}
/* Set default socket name. */
gServerName.sin_family = AF_INET;
gServerName.sin_port = htons (PORT);
gServerName.sin_addr.s_addr = htonl (INADDR_ANY);
// Log the exact command line used to start the program.
cmdIdx = 0;
cmdIdx += sprintf(&cmdLine[cmdIdx], "# %s", progname);
for (i=1; i<argc; i++)
{
cmdIdx += sprintf(&cmdLine[cmdIdx], " %s", argv[i]);
}
/*
* Process cmd line options.
*/
#ifdef __CYGWIN__
while ((ch = getopt (argc, argv, ":dhl:a:p:t:")) != -1)
#else
while ((ch = getopt (argc, argv, ":dha:p:t:")) != -1)
#endif
{
switch (ch)
{
case 'h':
usage (progname);
exit (0);
break;
case 'd':
gDebug = 1;
break;
case 'a':
if (strcmp (optarg, "localhost") == 0)
{
gServerName.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
}
else
{
gServerName.sin_addr.s_addr = inet_addr (optarg);
if (gServerName.sin_addr.s_addr == htonl (INADDR_NONE))
{
fprintf (stderr, "Bad bind address: %s\n", optarg);
exit (-1);
}
}
break;
case 'p':
{
uint16_t port = atoi (optarg);
if (port < 1024)
{
fprintf (stderr, "Can't bind to privileged port: %hu\n",
port);
exit (-1);
}
gServerName.sin_port = htons (port);
}
break;
case 't':
gMaxSockIdle = atoi (optarg) * SECS_PER_MIN;
if (gMaxSockIdle < 0)
{
fprintf (stderr, "Error: invalid timeout value\n");
exit (-1);
}
break;
#ifdef __CYGWIN__
case 'l':
strncpy (gLogFilename, optarg, sizeof gLogFilename);
break;
#endif
default:
fprintf (stderr, "\nUnknown option");
usage (progname);
exit (-1);
break;
}
}
/*
* Close all open file descriptors.
*/
close (STDIN_FILENO);
close (STDOUT_FILENO);
close (STDERR_FILENO);
/*
* Fork to detach from shell.
*/
if (fork () != 0)
{
exit (0); /* parent exits */
}
SYSLOG (LOG_USER, cmdLine);
SYSLOG (LOG_USER, "%s : port %hu",
gVersion, ntohs (gServerName.sin_port));
if (gDebug)
{
SYSLOG (LOG_USER, "Timeout = %d secs; local addr = %s", gMaxSockIdle,
inet_ntoa (gServerName.sin_addr));
}
mainLoop (); /* does not return */
exit (0);
}
Basically, as soon as a socket is accepted... I want to take the message that gets sent to the socket server. With the message (I believe it's in an array right?) I want to somehow explode the array like you can with PHP's explode and separate the values by a comma.
The first comma will be the password (I will check via a database against a table of IDs to see if it's in there). If it is in there, the program will insert the rest of the values in to another table and output OK.
Does anyone know how I could go about taking the array and separating it using something similar to PHP's explode function using commas?
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.