All pastes #1735210 Raw Edit

server.c

public c v1 · immutable
#1735210 ·published 2010-01-02 17:17 UTC
rendered paste body
#include <stdlib.h>#include <stdio.h>#include <stdint.h>#include <string.h>#include <sys/socket.h>#include <sys/select.h>#include <sys/types.h>#include <netdb.h>#include <unistd.h>typedef enum CONN_STATE_{  CONN_STATE_INACTIVE = 0,  CONN_STATE_CONNECTED,  CONN_STATE_LISTENING} CONN_STATE;typedef struct connection_{  struct connection_* next;  int                 sd;  int                 client_num;  CONN_STATE          state;  struct addrinfo*    peer_addr;} connection;connection* conn_create(connection** list){  connection* new = NULL;  int ret;  do  {    if (new = malloc(sizeof(connection)))    {      struct addrinfo hints = {};      hints.ai_family   = AF_INET;      hints.ai_socktype = SOCK_STREAM;      hints.ai_flags    = AI_PASSIVE;      if (0 == (ret = getaddrinfo("localhost", NULL, &hints, &(new->peer_addr))))      {        if (0 <= (new->sd = socket(AF_INET, SOCK_STREAM, 0)))        {          new->next       = NULL;          new->state      = CONN_STATE_INACTIVE;          new->client_num = 0;          if (list)          {            if (!*list)              *list = new;            else            {              new->next = *list;              *list = new;            }          }          break;          close(new->sd);        }        else          perror("socket: ");        freeaddrinfo(new->peer_addr);      }      else        printf("gai: %s\n", gai_strerror(ret));      free(new);      new = NULL;    }  } while (0);  return new;}void conn_destroy(connection* c){  if (c)  {    close(c->sd);    freeaddrinfo(c->peer_addr);    free(c);    c = NULL;  }}connection* create_listener(uint16_t port, connection** list){  connection*     listener  = NULL;  struct addrinfo hints     = {};  char            szPort[6] = {};  if (listener = conn_create(list))  {    hints.ai_family   = AF_INET;    hints.ai_socktype = SOCK_STREAM;    sprintf(szPort, "%hu", port);    printf("port: %s\n" , szPort);    do    {      freeaddrinfo(listener->peer_addr);      if (0 == getaddrinfo("localhost", szPort, &hints, &(listener->peer_addr)))        if (0 == bind(listener->sd, listener->peer_addr->ai_addr, listener->peer_addr->ai_addrlen))          if (0 == listen(listener->sd, 50))          {            listener->state = CONN_STATE_LISTENING;            break;          }      conn_destroy(listener);    } while (0);  }  return listener;}int main(int argc, char* argv[]){  connection* connections = NULL;  connection* new_conn    = NULL;  int         run         = 1;  if ((new_conn = create_listener(9090, &connections)))  {    int             ccount  = 0;    connection*     ptr;    printf("listen sd %d\n", new_conn->sd);    while (run)    {      int             max_fd = 0;      fd_set          rfds;      struct timeval  to      = {5, 0};      FD_ZERO(&rfds);      for (ptr = connections; ptr; ptr = ptr->next)        if (ptr->state != CONN_STATE_INACTIVE)        {          printf("select on %d\n", ptr->sd);          FD_SET(ptr->sd, &rfds);          if (ptr->sd > max_fd)            max_fd = ptr->sd;        }      switch (select(max_fd+1, &rfds, NULL, NULL, &to))      {        case -1:          perror("select: ");          run = 0;          break;        case 0:          printf("select timeout\n");          continue;        default:        {          for (ptr = connections; ptr; ptr = ptr->next)          {            if (FD_ISSET(ptr->sd, &rfds))            {              switch (ptr->state)              {                case CONN_STATE_CONNECTED:                {                  char buf[512] = {};                  int   nread   = 0;                  while (0 < (nread = recv(ptr->sd, &buf, 512, 0)))                  {                    printf("recieved %d bytes from client %d (%*s)\n", nread, ptr->client_num, nread, buf);                    if (nread < 512)                      break;                  }                  if (nread <= 0)                  {                    printf("client %d disconnected (%d)\n", ptr->client_num, nread);                    ptr->state = CONN_STATE_INACTIVE;                  }                  break;                }                case CONN_STATE_LISTENING:                {                  connection* new = conn_create(&connections);                  printf("someone trying to connect\n");                  if (new)                  {                    int new_sd;                    ptr->peer_addr->ai_addrlen = sizeof(struct sockaddr);                    if (0 <= (new_sd = accept(ptr->sd, new->peer_addr->ai_addr, &(new->peer_addr->ai_addrlen))))                    {                      new->client_num = ++ccount;                      close(new->sd);                      new->sd = new_sd;                      new->state = CONN_STATE_CONNECTED;                      printf("new client: %d\n", ccount);                    }                  }                  break;                }                default:                  continue;              }            }          }        }      }    }    for (ptr = connections; ptr;)    {      connection* del = ptr;      ptr = ptr->next;      conn_destroy(del);    }  }  return 0;}