ps_homeworks/dn1/server.cpp

149 lines
3.3 KiB
C++

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include <pthread.h>
#include <cstdlib>
#include <ctime>
#define PORT 10000
#define BUFFER_SIZE 256
#define MAX_CLIENTS 5
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_spinlock_t slock;
typedef struct _Client {
int clientSock;
long connection_start;
int sock_ix;
} Client;
Client clients[MAX_CLIENTS];
int check_if_there_is_space_for_client(Client *socks) {
printf("Searching for the first free client\n");
for(int i = 0; i < MAX_CLIENTS; i++) {
printf("%d: (%d), ", i, socks[i].sock_ix);
if (socks[i].sock_ix == -1) {
return i;
}
}
printf("\n");
return -1;
}
void *handle_client(void *arg) {
char buff[BUFFER_SIZE];
Client *c = (Client *)arg;
int clientSock = c->clientSock;
int sock_ix = c->sock_ix;
int iResult;
do{
iResult = recv(clientSock, buff, BUFFER_SIZE, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
iResult = send(clientSock, buff, iResult, 0 );
if (iResult == -1) {
printf("send failed!\n");
close(clientSock);
break;
}
printf("Bytes sent: %d\n", iResult);
}
else if (iResult == 0) {
printf("Closing connection(%d), lasted %ld seconds\n", sock_ix, time(NULL) - c->connection_start);
}
else{
printf("recv failed!\n");
close(clientSock);
break;
}
} while (iResult > 0);
close(clientSock);
pthread_spin_lock(&slock);
c->sock_ix = -1;
pthread_spin_unlock(&slock);
pthread_exit(NULL);
}
int main(int argc, char **argv){
int iResult;
int listener= socket(AF_INET, SOCK_STREAM, 0);
if (listener == -1) {
printf("Error creating clientSock\n");
return 1;
}
sockaddr_in listenerConf;
listenerConf.sin_port=htons(PORT);
listenerConf.sin_family=AF_INET;
listenerConf.sin_addr.s_addr=INADDR_ANY;
iResult = bind( listener, (sockaddr *)&listenerConf, sizeof(listenerConf));
if (iResult == -1) {
printf("Bind failed\n");
close(listener);
return 1;
}
if ( listen( listener, 5 ) == -1 ) {
printf( "Listen failed\n");
close(listener);
return 1;
}
int clientSock;
pthread_spin_init(&slock, PTHREAD_PROCESS_PRIVATE);
pthread_t t[MAX_CLIENTS];
Client clients[MAX_CLIENTS];
for(int i = 0; i < MAX_CLIENTS; i++) {
clients[i].sock_ix = -1;
}
while (1)
{
clientSock = accept(listener,NULL,NULL);
if (clientSock == -1) {
printf("Accept failed\n");
close(listener);
return 1;
}
pthread_spin_lock(&slock);
int sock_ix = check_if_there_is_space_for_client(clients);
pthread_spin_unlock(&slock);
if (sock_ix < 0) {
printf("Too many clients\n");
close(clientSock);
} else {
clients[sock_ix].sock_ix = sock_ix;
clients[sock_ix].clientSock = clientSock;
clients[sock_ix].connection_start = time(NULL);
printf("Hello i am new client and my idx is %d, my sock descriptor %d\n", sock_ix, clientSock);
pthread_create(&t[sock_ix], NULL, handle_client, (void *) &clients[sock_ix]);
}
}
close(listener);
pthread_spin_destroy(&slock);
return 0;
}