Untitled
Anonymous
plain_text
01/16/2026 7:54 AM
8.9 KB
11
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <stdbool.h>
#define MAX_MSG 1024
#define MAX_ROOMS 20
#define MAX_USERS 100
typedef struct {
char name[50];
struct sockaddr_in users[MAX_USERS];
int user_count;
} ChatRoom;
ChatRoom rooms[MAX_ROOMS];
int room_count = 0;
int sockfd;
int running = 1;
pthread_mutex_t lock;
/* UTILITY SERVER */
int find_room(const char* name) {
for (int i = 0; i < room_count; i++)
if (strcmp(rooms[i].name, name) == 0)
return i;
return -1;
}
void add_room(const char* name) {
if (room_count >= MAX_ROOMS) return;
strcpy(rooms[room_count].name, name);
rooms[room_count].user_count = 0;
room_count++;
}
int user_in_room(int room_id, struct sockaddr_in* user) {
for (int i = 0; i < rooms[room_id].user_count; i++) {
if (rooms[room_id].users[i].sin_addr.s_addr == user->sin_addr.s_addr &&
rooms[room_id].users[i].sin_port == user->sin_port)
return 1;
}
return 0;
}
void join_room(int room_id, struct sockaddr_in* user) {
if (!user_in_room(room_id, user)) {
rooms[room_id].users[rooms[room_id].user_count++] = *user;
}
}
void leave_room(int room_id, struct sockaddr_in* user) {
for (int i = 0; i < rooms[room_id].user_count; i++) {
if (rooms[room_id].users[i].sin_addr.s_addr == user->sin_addr.s_addr &&
rooms[room_id].users[i].sin_port == user->sin_port) {
rooms[room_id].users[i] = rooms[room_id].users[rooms[room_id].user_count - 1];
rooms[room_id].user_count--;
return;
}
}
}
void broadcast(int room_id, const char* msg, struct sockaddr_in* exclude) {
for (int i = 0; i < rooms[room_id].user_count; i++) {
if (exclude &&
rooms[room_id].users[i].sin_addr.s_addr == exclude->sin_addr.s_addr &&
rooms[room_id].users[i].sin_port == exclude->sin_port)
continue;
sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&rooms[room_id].users[i], sizeof(rooms[room_id].users[i]));
}
}
/* THREAD SERVER */
void* server_thread(void* arg) {
char buffer[MAX_MSG];
struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
while (running) {
int n = recvfrom(sockfd, buffer, MAX_MSG, 0, (struct sockaddr*)&sender, &sender_len);
if (n <= 0) continue;
buffer[n] = '\0';
pthread_mutex_lock(&lock);
if (strncmp(buffer, "/create ", 8) == 0) {
char room[50];
sscanf(buffer + 8, "%s", room);
if (find_room(room) == -1) {
add_room(room);
char msg[100];
sprintf(msg, "Stanza '%s' creata.\n", room);
sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&sender, sender_len);
} else {
sendto(sockfd, "Stanza già esistente.\n", 23, 0, (struct sockaddr*)&sender, sender_len);
}
}
else if (strncmp(buffer, "/join ", 6) == 0) {
char room[50];
sscanf(buffer + 6, "%s", room);
int id = find_room(room);
if (id == -1) {
sendto(sockfd, "Stanza inesistente.\n", 20, 0, (struct sockaddr*)&sender, sender_len);
} else {
join_room(id, &sender);
char msg[100];
sprintf(msg, ">> %s è entrato nella stanza.\n", inet_ntoa(sender.sin_addr));
broadcast(id, msg, NULL);
sendto(sockfd, "Entrato nella stanza.\n", 22, 0, (struct sockaddr*)&sender, sender_len);
}
}
else if (strncmp(buffer, "/leave", 6) == 0) {
for (int i = 0; i < room_count; i++) {
if (user_in_room(i, &sender)) {
leave_room(i, &sender);
char msg[100];
sprintf(msg, "<< %s è uscito dalla stanza.\n", inet_ntoa(sender.sin_addr));
broadcast(i, msg, NULL);
}
}
}
else if (strncmp(buffer, "/msg ", 5) == 0) {
char* text = buffer + 5;
for (int i = 0; i < room_count; i++) {
if (user_in_room(i, &sender)) {
char msg[200];
sprintf(msg, "[%s] %s\n", inet_ntoa(sender.sin_addr), text);
broadcast(i, msg, NULL);
}
}
}
else if (strcmp(buffer, "/quit") == 0) {
running = 0;
}
pthread_mutex_unlock(&lock);
}
return NULL;
}
/* CLIENT RECEIVER */
void* client_receiver(void* arg) {
char buffer[MAX_MSG];
struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
while (running) {
int n = recvfrom(sockfd, buffer, MAX_MSG, 0, (struct sockaddr*)&sender, &sender_len);
if (n > 0) {
buffer[n] = '\0';
printf("\n%s> ", buffer);
fflush(stdout);
}
}
return NULL;
}
/* MAIN */
int main() {
int scelta;
char ip[50];
int port;
pthread_mutex_init(&lock, 0);
do{
printf("MENU\n");
printf("1) SERVER\n");
printf("2) CLIENT\n");
scanf("%d", &scelta);
} while (scelta == 0);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (scelta == 1) {
printf("inserire la porta da utilizzare: ");
scanf("%d", &port);
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
printf("Server avviato sulla porta %d\n", port);
pthread_t t;
pthread_create(&t, NULL, server_thread, NULL);
pthread_join(t, NULL);
}
else { /* CLIENT */
printf("inserire l'ip del server: ");
scanf("%s", ip);
printf("inserire la porta del server: ");
scanf("%d", &port);
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
inet_pton(AF_INET, ip, &server_addr.sin_addr);
pthread_t t;
pthread_create(&t, NULL, client_receiver, NULL);
char msg[MAX_MSG];
getchar();
while (running) {
printf("> ");
fgets(msg, MAX_MSG, stdin);
msg[strcspn(msg, "\n")] = 0;
sendto(sockfd, msg, strlen(msg), 0,(struct sockaddr*)&server_addr, sizeof(server_addr));
if (strcmp(msg, "/quit") == 0) {
running = 0;
}
}
}
close(sockfd);
pthread_mutex_destroy(&lock);
return 0;
}Editor is loading...
Leave a Comment