Szanowni Państwo,
bardzo proszę o pomoc w dorobieniu kodu do zapytania:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#define MAXLOGIN 65
#define MAXCLIENTS 100
/*
1. Zakaz multilogowania - wylogować poprzedniego klienta
2. /receiver * - broadcast
3. informacje do użytkowników niezalogowanych są buforowane na serwerze (np. utworzyć na serwerze plik z nazwą klienta i po zalogowaniu dostaje wszystkie wiadomości)
*/
struct svc_arg *tab[MAXCLIENTS] = { NULL };
// przerabiamy tak aby każdy user mógł zobaczyć kto jest zalogowany
struct svc_arg
{
int sock;
char login[MAXLOGIN];
char receiver[MAXLOGIN];
FILE *in;
FILE *out;
};
int nclients = 0;
void *service(void *arg)
{
int i, poz;
int exitflag = 0;
struct svc_arg *a = (struct svc_arg *) arg;
if(nclients == MAXCLIENTS)
{
shutdown(a->sock, SHUT_RDWR); // żeby na niektórych wersjach nc działało
close(a->sock);
free(a);
return;
}
for(poz = 0; poz < MAXCLIENTS; poz++)
{
if(tab[poz] == NULL)
{
tab[poz] = a;
nclients++;
break;
}
}
pthread_detach(pthread_self());
//FILE *in = fdopen(a->sock, "r"); // wprowadzamy strumienie danych otwarty do odczytu
//FILE *out = fdopen(a->sock, "w"); // zapis
a->in = fdopen(a->sock, "r"); // wprowadzamy strumienie danych otwarty do odczytu
a->out = fdopen(a->sock, "w"); // zapis
setlinebuf(a->in);
setlinebuf(a->out);
//printf("%d\n", a->sock);
fprintf(a->out, "Welcome\n");
//fflush(out); // setlinebuf wysyła na bufor po zakończeniu linii
for(;;) // będziemy czytać łańcuch znaków
{
char buf[1024];
char cmd[1024];
char par[1024];
char text[1024];
int czyDoszlo;
if(!fgets(buf, sizeof(buf), a->in))
break;
int n = strlen(buf);
while(--n >= 0)
{
if(buf[n] == '\n' || buf[n] == '\r')
buf[n] = 0;
else
break;
}
//if(buf[0] == 'q') // wyłączenie serwera po wpisaniu q
//break;
switch(buf[0])
{
case 0:
break;
case '/':
// polecenie
par[0] = 0;
sscanf(buf + 1, "%s %s", cmd, par);
if(!strcmp(cmd, "quit"))
{
exitflag = 1;
break;
}
if(!strcmp(cmd, "ver"))
{
fprintf(a->out, "Ver 0.1\n");
break;
}
if(!strcmp(cmd, "login"))
{
for (i = 0; i < MAXCLIENTS; i++)
{
if (tab[i] != NULL && strcmp(tab[i]->login, a->login) && !strcmp(tab[i]->login, par))
{
shutdown(tab[i]->sock, SHUT_RDWR); // żeby na niektórych wersjach nc działało
close(tab[i]->sock);
// free
tab[i] = NULL;
// nclients--;
break;
}
//break;
}
strcpy(a->login, par);
char name[1024];
sprintf(name, "cache/%s", a->login);
FILE *f = fopen(name, "r");
if(f != NULL)
{
char buf[1024];
while(fgets(buf, 1024, f))
{
//fputs(buf, a->out);
fprintf(a->out, "%s", buf);
}
fclose(f);
unlink(name);
}
break;
}
if(!strcmp(cmd, "receiver"))
{
strcpy(a->receiver, par);
break;
}
if(!strcmp(cmd, "list"))
{
fprintf(a->out, "Liczba połączonych klientów: %d\n", nclients);
for(i = 0; i < MAXCLIENTS; i++)
{
if(tab[i] != NULL)
{
fprintf(a->out, "%3d %-17s %-17s\n", tab[i]->sock, tab[i]->login, tab[i]->receiver);
}
}
break;
}
if(!strcmp(cmd, "sendto"))
{
czyDoszlo = 0;
for(i = 0; i < MAXCLIENTS; i++)
{
if(tab[i] == NULL)
continue;
if(!strcmp(tab[i]->login, par))
{
strcpy(text, &buf[strlen(cmd) + strlen(par) + 3]);
fprintf(tab[i]->out, "%s > %s\n", a->login, text);
czyDoszlo = 1;
}
}
if(!czyDoszlo)
{
fprintf(a->out, "Wiadomość niedostarczona\n");
}
break;
}
if(!strcmp(cmd, "broadcast"))
{
for(i = 0; i < MAXCLIENTS; i++)
{
if(tab[i] == NULL)
continue;
strcpy(text, &buf[strlen(cmd) + 2]);
fprintf(tab[i]->out, "%s > %s\n", a->login, text);
}
break;
}
fprintf(a->out, "ERRCMD %s\n", cmd);
break;
default:
// dane
fprintf(a->out, "%s > %s\n", a->login, buf);
//for (i = 0; buf[i] != 0; i++)
//{
// printf("%d ", buf[i]);
//}
czyDoszlo = 0;
for(i = 0; i < MAXCLIENTS; i++)
{
if(tab[i] == NULL)
continue;
if((!strcmp(a->receiver, "*") && strcmp(tab[i]->login, a->login)) || !strcmp(tab[i]->login, a->receiver))
{
fprintf(tab[i]->out, "%s > %s\n", a->login, buf);
czyDoszlo = 1;
}
}
if(!czyDoszlo)
{
fprintf(a->out, "Wiadomość będzie dostarczona jak sie zaloguje\n");
char name[1024];
sprintf(name, "cache/%s", a->receiver);
FILE *f = fopen(name, "a");
if(f != NULL)
{
fputs(buf, f);
fputs("\n", f);
fclose(f);
}
}
break;
}
if(exitflag)
break;
}
shutdown(a->sock, SHUT_RDWR); // żeby na niektórych wersjach nc działało
close(a->sock);
//free(arg);
tab[poz] = NULL;
free(a);
nclients--;
return NULL;
}
main()
{
struct sockaddr_in server;
int sock, opt;
struct svc_arg *a;
pthread_t tid;
sock = socket(AF_INET, SOCK_STREAM, 0); // funckja socket która działa strumieniowo to jest opcja gdzie nie trzeba czekać minuty na ponowne połączenie
opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
memset(&server, 0, sizeof(server)); // zeruje strukturę
server.sin_family = AF_INET; // w sieci internet
server.sin_port = htons(10917); // port
if (bind(sock, (struct sockaddr *) &server, // funckja nie wywoła się jeśli port jest zajęty lub port jest mniejszy lub równy 1024 (tylko dla admina)
sizeof(server))) {
perror("bind");
exit(1);
}
listen(sock, 5); // gdniazdko jest nasłuchowe - 5 - mówi że kolejka oczekujących klientów może być 5 (większość nowych systemów olewa ten parametr)
for (;;)
{
//a = (struct svc_arg *) malloc(sizeof(struct svc_arg)); // alokuje miejsce na strukturę serwera svc_arg to nasza struktura
a = (struct svc_arg *) calloc(1, sizeof(struct svc_arg));
a->sock = accept(sock, NULL, NULL);
pthread_create(&tid, NULL, service, a); // serwis obsługuje klienta
}
}
generalnie chodzi o dorobienie blokowania kowalskiego (od blokowanego nie dochodzi wiadomość do mnie )
dodatkowo chciałbym aby zablokowany otrzymywał informację, że jest zablokowany.
Będę wdzięczny za bardzo szybką pomoc.