Last active
August 29, 2015 14:10
-
-
Save seronis/b5119afc095a5c58f260 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <errno.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <netdb.h> | |
#define PORT 5000 | |
#define MAXMSG 1025 | |
typedef struct client { | |
int sockid; | |
char path[1024]; | |
char inbuffer[1024]; | |
struct client * next; | |
struct client * prev; | |
} client_t; | |
client_t * listHead = NULL; | |
client_t * listTail = NULL; | |
client_t * new_client( _sock ) | |
{ | |
client_t * p = malloc( sizeof( client_t ) ); | |
p->sockid = _sock; | |
p->path[0] = '\0'; | |
p->next = NULL; | |
p->prev = NULL; | |
return p; | |
} | |
void list_addClient( client_t * _client, int add_to_head ) | |
{ | |
if ( listHead == NULL ) { | |
listHead = listTail = _client; | |
return; | |
} | |
if ( add_to_head != 0 ) { | |
_client->next = listHead; | |
listHead->prev = _client; | |
listHead = _client; | |
} else { | |
_client->prev = listTail; | |
listTail->next = _client; | |
listTail = _client; | |
} | |
} | |
void list_remClient( client_t * _client ) | |
{ | |
if ( listHead == _client ) { | |
listHead = _client->next; | |
} | |
if ( listTail == _client ) { | |
listTail = _client->prev; | |
} | |
if ( _client->prev != NULL ) { | |
_client->prev->next = _client->next; | |
} | |
if ( _client->next != NULL ) { | |
_client->next->prev = _client->prev; | |
} | |
} | |
int read_from_client( client_t * _client ) | |
{ | |
int nbytes; | |
nbytes = read( _client->sockid, _client->inbuffer, 512 ); | |
if ( nbytes > 0 ) { | |
_client->inbuffer[nbytes] = '\0'; | |
return 1; | |
} else if ( nbytes == 0 ) { | |
return 0; | |
} else if ( errno == EAGAIN ) { | |
return 1; | |
} else { | |
return 0; | |
} | |
} | |
int main( void ) | |
{ | |
//extern int make_socket (uint16_t port); | |
int sock; | |
fd_set active_fd_set, read_fd_set; | |
struct sockaddr_in clientname; | |
; | |
//size_t size; | |
unsigned int size; | |
/* Create the socket and set it up to accept connections. */ | |
//sock = make_socket (PORT); | |
if ( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) { | |
perror( "Server-socket() error lol!" ); | |
/*just exit lol!*/ | |
exit( 1 ); | |
} | |
printf( "Server-socket() is OK...\n" ); | |
/*"address already in use" error message */ | |
int yes = 1; | |
if ( setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof( int ) ) == -1 ) { | |
perror( "Server-setsockopt() error lol!" ); | |
exit( 1 ); | |
} | |
printf( "Server-setsockopt() is OK...\n" ); | |
/* bind */ | |
clientname.sin_family = AF_INET; | |
clientname.sin_addr.s_addr = htonl( INADDR_ANY ); | |
clientname.sin_port = htons( 5000 ); | |
//memset(clientname.sin_zero, '\0', 8); | |
if ( bind( sock, ( struct sockaddr * )&clientname, sizeof( clientname ) ) == -1 ) { | |
perror( "Server-bind() error lol!" ); | |
exit( 1 ); | |
} | |
printf( "Server-bind() is OK...\n" ); | |
if ( listen( sock, 1 ) < 0 ) { | |
perror( "listen" ); | |
exit( EXIT_FAILURE ); | |
} | |
/* Initialize the set of active sockets. */ | |
FD_ZERO( &active_fd_set ); | |
FD_SET( sock, &active_fd_set ); | |
while ( 1 ) { | |
/* Block until input arrives on one or more active sockets. */ | |
read_fd_set = active_fd_set; | |
if ( select( FD_SETSIZE, &read_fd_set, NULL, NULL, NULL ) < 0 ) { | |
perror( "select" ); | |
exit( EXIT_FAILURE ); | |
} | |
//check for incomming connections | |
if ( FD_ISSET( sock, &read_fd_set ) ) { | |
int sockid; | |
size = sizeof( clientname ); | |
sockid = accept( sock, ( struct sockaddr * ) &clientname, & size ); | |
if ( sockid < 0 ) { | |
perror( "accept failure: abandoning this client" ); | |
} else { | |
client_t * newSock = new_client( sockid ); | |
list_addClient( newSock, 1 ); | |
fprintf( stderr, | |
"Server: new connection from host %s, port %hd.\n", | |
inet_ntoa( clientname.sin_addr ), | |
ntohs( clientname.sin_port ) ); | |
FD_SET( sockid, &active_fd_set ); | |
} | |
} | |
//process all connected clients | |
client_t * check = listHead; | |
client_t * check_next = listHead; | |
while ( check != NULL ) { | |
check_next = check->next; //needed because we might delete clients while navigating list; | |
if ( FD_ISSET( check->sockid, &read_fd_set ) ) { | |
//TODO: read data from client | |
if ( read_from_client(check) == 0) { | |
list_remClient( check ); | |
FD_CLR(check->sockid,&active_fd_set); | |
free(check); | |
} else { | |
fprintf( stderr, "Server: got message: `%s'\n", check->inbuffer ); | |
} | |
} | |
check = check_next; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment