Search code examples
ctcpclients

Limit and identify clients TCP


I have this program that is prototype for a game of connectfour, as a homework project. So far so good, but I have major question, how do I limit the clients to only 2 of them, and also, how can I easily identify them when I am going to verify which column pick comes from which one?

    #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>

//used port
#define PORT 6660
//array limits
#define WIDTH 7
#define HEIGTH 6

//error code for some applications
extern int errno;

//static column variables

static int gameVariables [WIDTH] = {6, 6, 6, 6, 6, 6, 6};
static char gameArray[HEIGTH][WIDTH];

static void *treat(void *);//function called by every thread
typedef struct thData
{
  pthread_t idThread; //id Thread
  int cl;//descriptor returned by accept
}thData;

//Thread *threadsPool; //Threads array

//int sd;//listenning socket descriptor
//int nthreads; //number of threadsPool

//pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER; //mutex variable
static void *treat(void *);
//void raspunde (void *);
void connectFour(void *);

void printArray( char array[HEIGTH][WIDTH])
{
  int k, j;
 for( k = 0; k < HEIGTH; k++ )
    {
      for( j=0; j < WIDTH; j++ )
        printf("%c ", array[k][j]);
      printf("\n");
    }
}

int main( )
{
  //game array inialization
  int k, j;
  for( k = 0; k < HEIGTH; k++ )
    for( j = 0; j < WIDTH; j++ )
      gameArray[k][j] = (char) 79;


   printArray(gameArray);

  struct sockaddr_in server; //structure used by server
  //void threadCreate(int);
  struct sockaddr_in from;
  int message;
  int sd;
  int pid;
  pthread_t th[100];
  int i = 0;
  /*if(argc < 2)
  {
    fprintf(stderr, "Error: first argument is the number of thread\n");
    exit(1);
  } 

  nthreads = atoi(argv[1]);
  if(nthreads <= 0)
  {
    fprintf(stderr,"Error: number of threads invalid\n");
    exit(1);
  }

  threadsPool = calloc(sizeof(Thread), nthreads);
*/
  //create socket
  if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    perror("[SERVER] Error at socket\n");
    return errno;
  }

  //using SO_REUSEADDR
  int on = 1;
  setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

  //preparing data structures
  bzero(&server, sizeof(server));
  bzero(&from, sizeof(from));

  server.sin_family = AF_INET;
  server.sin_addr.s_addr = htonl(INADDR_ANY);
  server.sin_port = htons(PORT);

  //bind the socket
  if(bind(sd, (struct sockaddr *) &server, sizeof(struct sockaddr) )== -1)
  {
    perror("[SERVER] Error at bind\n");
    return errno;
  }

  //server listening
  if(listen(sd, 2) == -1)
  {
    perror("[SERVER] Error at listen\n");
    return errno;
  }

 /* printf("Number of threads %d\n", nthreads);
  fflush(stdout);

  int i;
  for(i = 0; i < nthreads; i++)
    threadCreate(i);

  //serving concurrent clients using threads
  for( ; ; )
  {
    printf("[SERVER] Listening at port : %d", PORT);
    pause();
  }//for
*/
  //serving clients
  for( ; ; )
  {
    int client;
    thData *td; //parameter executed by thread
    int length = sizeof(from);

    printf("[SERVER] Waiting at port : %d\n", PORT);
    fflush(stdout);
    //accept client
    if((client = accept (sd, (struct sockaddr *) &from, &length)) < 0)
    {
      perror ("[SERVER]Error at accept\n");
      continue;
    }
    //connection established
    int idThread; //thread id
    int cl;

    td = (struct thData*)malloc(sizeof(struct thData));
    td -> idThread = i++;
    td -> cl = client;

    pthread_create (&th[i], NULL, &treat, td);
  } //for
};//main

static void *treat(void * arg)
{   
  struct thData tdL; 
  tdL= *((struct thData*)arg);  
  printf ("[thread]- %d - Waiting message\n", tdL.idThread);
  fflush (stdout);     
  pthread_detach(pthread_self());   
  connectFour((struct thData*)arg);
  /* am terminat cu acest client, inchidem conexiunea */
  close ((int)arg);
  return(NULL); 

};

/*
void raspunde (void *arg)
{
  int i = 0;
  char message[50], message2[100];
  struct thData tdL;
  tdL = *((struct thData*) arg);
  bzero(message, 50);
  if(read(tdL.cl, message, 50) <= 0)
  {
    printf("[thread %d]\n", tdL.idThread);
    perror("Error at read from client\n");
  }

  printf("[thread %d] Message was received %s\n", tdL.idThread, message);
  //preparing answer
  /*bzero(message2, 100);
  strcat(message2, "Hello, ");
  strcat(message2, message);
  printf("[thread %d] Sending back message %s\n", tdL.idThread, message2);

  //returning message
  if(write(tdL.cl, message2, 100) <= 0)
  {
    printf("[thread %d]\n", tdL.idThread);
    perror("[thread] Error at write\n");
  }
  else 
    printf("[thread %d] Message was sent with success\n", tdL.idThread);
};
*/

void connectFour( void *arg)
{

  int playerPick;
  char message[50];

  struct thData tdL;
  tdL = *((struct thData*) arg);
  bzero(message, 2);

  if(read (tdL.cl, message, 50) <= 0)
  {
    printf("[thread %d]\n", tdL.idThread );
    perror("Error at read from client\n");
  }

  printf ("[thread %d]Column pick received is : %s\n", tdL.idThread, message);
  playerPick = atoi(message);

  printf("playerPick is : %d\n", playerPick);
  fflush(stdout);
  switch(playerPick)
  {
    case 1:
     if(gameVariables[0] >0 && gameVariables[0] < 7)
      {
        --gameVariables[0];
        gameArray[gameVariables[0]][0] = (char) 82;
      }
      printArray(gameArray);
      break;
    case 2:

      if(gameVariables[1] >0 && gameVariables[1] < 7)
      {
        --gameVariables[1];
        gameArray[gameVariables[1]][1] = (char) 82;
      }
      printArray(gameArray);
      break;
    case 3:
      if(gameVariables[2] >0 && gameVariables[2] < 7)
        {
          --gameVariables[2];
          gameArray[gameVariables[2]][2] = (char) 82;
        }
      printArray(gameArray);
      break;
    case 4:
      if(gameVariables[3] >0 && gameVariables[3] < 7)
        {
          --gameVariables[3];
          gameArray[gameVariables[3]][3] = (char) 82;
        }
      printArray(gameArray);
      break;
    case 5:
      if(gameVariables[4] >0 && gameVariables[4] < 7)
      {
        --gameVariables[4];
        gameArray[gameVariables[4]][4] = (char) 82;
      }
      printArray(gameArray);
      break;
    case 6:
      if(gameVariables[5] >0 && gameVariables[5] < 7)
      {
        --gameVariables[5];
        gameArray[gameVariables[5]][5] = (char) 82;
      }
      printArray(gameArray);
      break;
    case 7:
      if(gameVariables[6] >0 && gameVariables[6] < 7)
      {
        --gameVariables[6];
        gameArray[gameVariables[6]][6] = (char) 82;
      }
      printArray(gameArray);
      break;

  }
  printf("%d %d %d %d %d %d %d\n", gameVariables[0], gameVariables[1], gameVariables[2], gameVariables[3], gameVariables[4], gameVariables[5], gameVariables[6]);


}

;


Solution

  • You simply keep a counter that you check when accepting connections. When a client connect you check the counter and if it's beyond the limit then close the connection, else you keep the connection and increase the counter. When a client disconnects (for whatever reason) you decrease the counter.


    It's important that you actually accept all connection, even if you just close them again immediately. This is because the queue of sockets waiting for accept is not limitless. Once you fill it up no more clients will be able to connect.