#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include<sys/time.h>
#include<sys/types.h>
#include <pthread.h>
#define BUFFER_SIZE 32
{
int newfd = (int)parameter;
int idleTimeout = 30;
int exitFlag = 0;
int nBytes = 0;
fd_set fdread;
fd_set fdwrite;
struct timeval timeout;
FD_ZERO(&fdread);
FD_SET(newfd, &fdread);
FD_ZERO(&fdwrite);
FD_SET(newfd, &fdwrite);
while(1)
{
timeout.tv_sec = idleTimeout;
timeout.tv_usec = 0;
switch(select(newfd + 1, &fdread, NULL, NULL, &timeout))
{
case -1:
printf("Server: connection[%d] closed.\r\n", newfd);
exitFlag = 1;
close(newfd);
break;
case 0:
printf("Server: connection[%d] timeout, closed.\r\n", newfd);
exitFlag = 1;
close(newfd);
break;
default:
if(FD_ISSET(newfd, &fdread))
{
timeout.tv_sec = idleTimeout;
timeout.tv_usec = 0;
memset(buf, 0, sizeof(buf));
nBytes = read(newfd, buf, sizeof(buf));
if(nBytes == -1 || nBytes == 0)
{
printf("Server: connection[%d] closed.\r\n", newfd);
exitFlag = 1;
close(newfd);
break;
}
printf("Server: connection[%d] reads %d bytes.\r\n", newfd, nBytes);
timeout.tv_sec = idleTimeout;
timeout.tv_usec = 0;
if(select(newfd + 1, NULL, &fdwrite, NULL, &timeout) > 0)
{
if(FD_ISSET(newfd, &fdwrite))
{
nBytes = write(newfd, buf, nBytes);
if(nBytes == -1 || nBytes == 0)
{
printf("Server: connection[%d] closed.\r\n", newfd);
exitFlag = 1;
close(newfd);
break;
}
}
}
printf("Server: connection[%d] writes %d bytes.\r\n", newfd, nBytes);
}
break;
}
if(exitFlag == 1) break;
}
}
int main(
int argc,
char* argv[])
{
int rc = 0;
int sinSize = 0;
int sockfd = 0;
int newfd = 0;
int backlog = 10;
unsigned short port = 2323;
int reuseaddr = 1;
socklen_t reuseaddr_len = sizeof(reuseaddr);
pthread_t thread;
struct sockaddr_in sockAddress;
struct sockaddr_in clientAddress;
while((rc = getopt(argc, argv, "hp:")) != -1)
{
switch(rc)
{
case 'p':
port = atoi(optarg);
break;
case '?':
case 'h':
default:
printf("Echo Server, server program.\n\n");
printf("Usage: ./server_tcp_echo [OPTIONS]\n\n");
printf("Options:\n");
printf("\t%-8s Port [%d-%d]. Default port = %d\n", "-p", 0, 65535, port);
printf("\n");
return;
}
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
sockAddress.sin_family = AF_INET;
sockAddress.sin_port = htons(port);
sockAddress.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&(sockAddress.sin_zero), 8);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, reuseaddr_len);
if(bind(sockfd, (struct sockaddr*)&sockAddress, sizeof(struct sockaddr)) == -1)
{
close(sockfd);
perror("bind");
exit(1);
}
if(listen(sockfd, backlog) == -1)
{
close(sockfd);
perror("listen");
exit(1);
}
sinSize = sizeof(struct sockaddr_in);
printf("Server: started at port:%d.\r\n", port);
while(1)
{
if((newfd = accept(sockfd, (struct sockaddr*)&clientAddress, &sinSize)) == -1)
{
close(sockfd);
perror("accept");
exit(1);
}
if(rc != 0)
{
close(newfd);
continue;
}
else
{
pthread_detach(thread);
printf("Server: connection[%d] established.\r\n", newfd);
}
}
close(sockfd);
return 0;
}