Skip to content

Instantly share code, notes, and snippets.

@seronis
Last active August 29, 2015 14:10
Show Gist options
  • Save seronis/b5119afc095a5c58f260 to your computer and use it in GitHub Desktop.
Save seronis/b5119afc095a5c58f260 to your computer and use it in GitHub Desktop.
#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