我想创建一个聊天室,其服务器接受任何客户端,当一个客户端发送一些文本时,服务器会将该消息发送给当时连接的所有其他客户端。到目前为止,我的服务器能够接受许多客户端(通过套接字连接),并且可以发送服务器显示的消息。我的服务器有一个结构,用于随时了解谁(名称和PID)已连接。我的问题是:我怎样才能使我的服务器将从1个客户端收到的消息重定向到所有其他客户端?
Server.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/mman.h>
typedef struct tabela
{
char name[50];
int PID;
} tab;
static tab *tabelaPersoane;
static int *nrPersoaneConectate;
void afisareConectati()
{
int i;
if (*nrPersoaneConectate > 0)
{
printf("Numarul de persoane conectate: %d", *nrPersoaneConectate);
printf("\nPersoane conectate:\n");
for (i = 0; i < *nrPersoaneConectate; i++)
{
printf("%s", tabelaPersoane[i].name);
}
printf("\n");
}
else
printf("Niciun client conectat!\n");
}
void doprocessing(int sock, char *numeClient)
{
//printf("doprocessing id=%d\n",sock);
int n, i;
char buffer[256], mesaj[256];
while (1)
{
//printf("%d\n",nrPersoaneConectate);
bzero(buffer, 256);
n = read(sock, buffer, 255);
if (strncmp(buffer, "exit", strlen("exit")) == 0)
{
for (i = 0; i < *nrPersoaneConectate; i++)
{
if (strcmp(numeClient, tabelaPersoane[i].name) == 0)
if (i != *nrPersoaneConectate - 1)
{
tabelaPersoane[i] = tabelaPersoane[*nrPersoaneConectate - 1];
//printf("%d\n",nrPersoaneConectate);
}
}
(*nrPersoaneConectate)--;
printf("S-a deconectat %s", numeClient);
afisareConectati();
break;
}
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
if (strcmp(buffer, "") != 0)
{
bzero(mesaj, 256);
strncpy(mesaj, numeClient, strlen(numeClient) - 1);
strcat(mesaj, ": ");
strncat(mesaj, buffer, strlen(buffer));
printf("%s", mesaj);
}
n = write(sock, "I got your message", 18);
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
}
}
int main(int argc, char *argv[])
{
nrPersoaneConectate = mmap(NULL, sizeof *nrPersoaneConectate,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
tabelaPersoane = (tab *) mmap(0, sizeof(tab), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
int sockfd, newsockfd, portno, clilen;
char buffer[256], mesaj[256];
char buffer_pid[6];
struct sockaddr_in serv_addr, cli_addr;
int n, i;
*nrPersoaneConectate = 0;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 51100;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
if (listen(sockfd, 5) < 0)
{
printf("error ...");
exit(1);
}
clilen = sizeof(cli_addr);
while (1)
{
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
//printf("sockfd%d\n",sockfd);
//printf("newsockfd%d\n",newsockfd);
if (newsockfd < 0)
{
perror("ERROR on accept");
exit(1);
}
(*nrPersoaneConectate)++;
/* Create child process */
int pid = fork();
if (pid < 0)
{
perror("ERROR on fork");
exit(1);
}
if (pid == 0)
{
/* This is the client process */
close(sockfd);
if (write(newsockfd, "Name: ", sizeof("Name: ")) < 0)
{
printf("Error on sending \"Name: \" string.");
exit(1);
}
if (read(newsockfd, buffer, 255) < 0)
{
printf("Error on reading the name response.");
exit(1);
}
strcpy(tabelaPersoane[(*nrPersoaneConectate) - 1].name, buffer);
tabelaPersoane[(*nrPersoaneConectate) - 1].PID = getpid();
bzero(mesaj, 256);
strcpy(mesaj, "S-a conectat ");
strncat(mesaj, buffer, strlen(buffer) - 1);
strcat(mesaj, " PID: ");
sprintf(buffer_pid, "%d", tabelaPersoane[(*nrPersoaneConectate) - 1].PID);
strcat(mesaj, buffer_pid);
strcat(mesaj, "\n");
printf("%s", mesaj);
afisareConectati();
doprocessing(newsockfd, buffer);
exit(0);
}
else
{
close(newsockfd);
//printf("Close\n");
}
} /* end of while */
}
Client.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL )
{
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
/* Now connect to the server */
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR connecting");
exit(1);
}
if (read(sockfd, buffer, 255) < 0)
{
printf("Error on reading \"Name: \" string.");
exit(1);
}
printf("%s", buffer);
bzero(buffer, 256);
fgets(buffer, 255, stdin);
fflush(stdin);
if (write(sockfd, buffer, sizeof(buffer)) < 0)
{
printf("Error on sending %s", buffer);
exit(1);
}
/* Now ask for a message from the user, this message
* will be read by server
*/
while (1)
{
printf("Please enter the message: ");
bzero(buffer, 256);
fgets(buffer, 255, stdin);
//printf("buffer=%s\n",buffer);
if (strncmp(buffer, "exit", strlen("exit")) == 0)
{
//printf("Am iesit din while!\n(Din client)");
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
break;
}
/* Send message to the server */
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
/* Now read server response */
bzero(buffer, 256);
n = read(sockfd, buffer, 255);
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
//strcpy(buffer,"");
//fflush(stdin);
}
return 0;
}