Skip to content

Instantly share code, notes, and snippets.

@yifu
Created September 21, 2012 15:05
Show Gist options
  • Select an option

  • Save yifu/3762040 to your computer and use it in GitHub Desktop.

Select an option

Save yifu/3762040 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#define RCVBUFSIZE 32 /* Size of receive buffer */
void DieWithError(char *errorMessage); /* Error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
unsigned short echoServPort; /* Echo server port */
char *servIP; /* Server IP address (dotted quad) */
char *echoString; /* String to send to echo server */
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
unsigned int echoStringLen; /* Length of string to echo */
int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv()
and total bytes read */
if ((argc < 3) || (argc > 4)) /* Test for correct number of arguments */
{
fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n",
argv[0]);
exit(1);
}
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
//echoString = argv[2]; /* Second arg: string to echo */
echoString = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; /* Second arg: string to echo */
if (argc == 4)
echoServPort = atoi(argv[3]); /* Use given port, if any */
else
echoServPort = 7; /* 7 is the well-known port for the echo service */
/* Create a reliable, stream socket using TCP */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
/* Establish the connection to the echo server */
if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("connect() failed");
echoStringLen = strlen(echoString); /* Determine input length */
// NON BLOCKING!
int flags = fcntl (sock, F_GETFL, 0 );
fcntl (sock, F_SETFL, flags | O_NONBLOCK );
/* Send the string to the server. */
int sent = 0;
do
{
std::cout << "Send?" << std::endl;
if ((sent = send(sock, echoString, echoStringLen, 0)) == -1)
{
const int errNumber = errno;
if (errNumber == EWOULDBLOCK || errNumber == EAGAIN)
{
std::cout << "First slow consuming here: [" << sent << "]" << std::endl;
break;
}
}
std::cout << "Sent! [" << sent << "]." << std::endl;
}
while (true);
// SELECT
int servSock[1]; /* Socket descriptors for server */
servSock[0] = sock;
int maxDescriptor = echoServPort; /* Maximum socket descriptor value */
fd_set sockSet; /* Set of socket descriptors for select() */
long timeout = 1; /* Timeout value given on command-line */
struct timeval selTimeout; /* Timeout for select() */
int running = 1; /* 1 if server should be running; 0 otherwise */
int noPorts = 1; /* Number of port specified on command-line */
int port; /* Looping variable for ports */
unsigned short portNo; /* Actual port number */
while (running)
{
/* Zero socket descriptor vector and set for server sockets */
/* This must be reset every time select() is called */
FD_ZERO(&sockSet);
/* Add socket to descriptor vector */
FD_SET(sock, &sockSet);
/* Timeout specification */
/* This must be reset every time select() is called */
selTimeout.tv_sec = timeout; /* timeout (secs.) */
selTimeout.tv_usec = 0; /* 0 microseconds */
/* Suspend program until descriptor is ready or timeout */
if (select(maxDescriptor + 1, NULL, &sockSet, NULL, &selTimeout) == 0)
printf("No echo requests for %ld secs...Server still alive\n", timeout);
else
{
if (FD_ISSET(sock, &sockSet)) /* Ready for write !!*/
{
printf("Ready for write!!!!!! \n");
// running = 0;
if ((sent = send(sock, echoString, echoStringLen, 0)) == -1)
{
const int errNumber = errno;
if (errNumber == EWOULDBLOCK || errNumber == EAGAIN)
{
std::cout << "Slow consuming here: [" << sent << "]" << std::endl;
}
}
else
{
std::cout << "Sent! [" << sent << "]." << std::endl;
}
}
}
}
printf("\n"); /* Print a final linefeed */
close(sock);
exit(0);
}
void DieWithError(char *errorMessage)
{
perror(errorMessage);
exit(1);
}
int AcceptTCPConnection(int servSock)
{
int clntSock; /* Socket descriptor for client */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int clntLen; /* Length of client address data structure */
/* Set the size of the in-out parameter */
clntLen = sizeof(echoClntAddr);
/* Wait for a client to connect */
if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr,
&clntLen)) < 0)
DieWithError("accept() failed");
/* clntSock is connected to a client! */
printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr));
return clntSock;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment