Ограничить и идентифицировать клиентов TCP
У меня есть эта программа, которая является прототипом для игры connectfour, как домашнее задание. Пока все хорошо, но у меня есть главный вопрос: как мне ограничить клиентов только двумя из них, а также, как я могу легко идентифицировать их, когда я собираюсь проверить, какой выбор столбца происходит из какого?
#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]);
}
;
1 ответ
Вы просто сохраняете счетчик, который вы проверяете, принимая соединения. Когда клиент подключается, вы проверяете счетчик и, если он превышает лимит, затем закрываете соединение, иначе вы сохраняете соединение и увеличиваете счетчик. Когда клиент отключается (по какой-либо причине), вы уменьшаете счетчик.
Важно, чтобы вы фактически приняли все соединения, даже если вы сразу же закроете их снова. Это потому, что очереди сокетов ждут accept
не безграничен После того, как вы заполните его, клиенты больше не смогут подключиться.