Codice PHP:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#define SHOW 1 // command show
#define MESSAGE 2
#define HELP 3
#define NICK 4
#define NEWLINE 5
void write_to_socket(int target,char *buff_to_send,int len);
int check_for_command(char *buffer,int *p);
int is_fd_valid(int destination) ;
void type_writer(char *buf,int len,int fd);
typedef struct
{
int id; /* socket descripter */
char nick[30]; /* store the nick here */
short flag_nick;
}USER;
USER user[20];
int usercount=0;
int main(int argc, char *argv[])
{
fd_set master; // master file descriptor list
fd_set read_fds; // temp file descriptor list for select()
int PORT; // porta sulla quale il server resta in ascolto
struct sockaddr_in myaddr; // server address
struct sockaddr_in remoteaddr; // client address
int fdmax; // maximum file descriptor number
int listener; // listening socket descriptor
int newfd; // newly accept()ed socket descriptor
char buf[1024]; // buffer for client data
int nbytes;
int yes=1; // for setsockopt() SO_REUSEADDR, below
int addrlen;
int i, j,k,tmp,destination=0;
int str_len;
char c;
char *tmp_ptr;
//USER user[20];
//int usercount=0;
bzero(user,sizeof(USER));
FD_ZERO(&master); // clear the master and temp sets
FD_ZERO(&read_fds);
if (argc != 2) {
fprintf(stderr, "Sintassi: %s <porta>\n", argv[0]);
exit(4);
}
PORT=atoi(argv[1]);
// get the listener
if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(1);
}
// lose the pesky "address already in use" error message
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt error");
exit(1);
}
// bind
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(PORT);
memset(&(myaddr.sin_zero), '\0', 8);
if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
perror("bind error");
exit(1);
}
// listen
if (listen(listener, 10) == -1) {
perror("listen error");
exit(1);
}
// add the listener to the master set
FD_SET(listener, &master);
// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one
// main loop
for(;;) {
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(1);
}
// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == listener) {
// handle new connections
addrlen = sizeof(remoteaddr);
if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr,
&addrlen)) == -1) {
perror("accept error");
} else {
FD_SET(newfd, &master); // add to master set
if (newfd > fdmax) { // keep track of the maximum
fdmax = newfd;
}
user[usercount].id=newfd;
++usercount;
printf(">> Accettata nuova connessione dal client %s sul socket %d\n", inet_ntoa(remoteaddr.sin_addr), newfd);
bzero(buf,sizeof(buf));
strcpy(buf,"\n\n\n\n\n\n\n\n\n\n\n********************************************************************************\n");
str_len=strlen(buf);
write_to_socket(newfd,buf,str_len);
bzero(buf,sizeof(buf));
strcpy(buf,"\n\t\t\t ~~~~ BATTAGLIA NAVALE ~~~~\n\n");
str_len=strlen(buf);
type_writer(buf,str_len,newfd);
user[1].flag_nick=1;
strncpy(user[1].nick,"nick",30);
bzero(buf,sizeof(buf));
strcpy(buf,"********************************************************************************\n\n"
"\t\t\t~Type /SHOW/ to list all online users\n\n"
"\t~ To send a message to everyone in the room just type the message and press enter\n\n"
"\t\t~ Type /numeric-user/ to send a message to particular user only\n\n"
"\t\t ex: /6/ Hi number 6 how r u\n\n"
"\t\t\t~ Type /HELP/ to see server commands\n\n"
"********************************************************************************\n\n\n>>");
/* sprintf(buf,"Il nickname scelto e': ",user[1].nick);
str_len=strlen(buf);
write_to_socket(i,buf,str_len); */
str_len=strlen(buf);
write_to_socket(newfd,buf,str_len);
}
} else {
// handle data from a client
if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {
// got error or connection closed by client
if (nbytes == 0) {
// connection closed
printf(">> Socket %d chiuso. Il client %s si e' disconnesso.\n", i, inet_ntoa(remoteaddr.sin_addr));
} else {
perror("recv");
}
close(i); // bye!
FD_CLR(i, &master); // remove from master set
} else {
// we got some data from a client
//printf("\n%s\n",buf);
for(j = 0; j <= fdmax; j++) {
// send to everyone!
if (FD_ISSET(j, &master)) {
// except the listener and ourselves
if (j != listener && j != i) {
switch(check_for_command(buf,&destination))
{
case SHOW:
//strcpy(buf,"Got the command request :-)\n>>\r\n" );
//str_len=strlen(buf);
k= usercount-1;
bzero(buf,sizeof(buf));
while(k>=0)
{
sprintf(buf,"<%d>\n>>",user[k].id);
str_len=strlen(buf);
write_to_socket(i,buf,str_len);
--k;
}
j=1111; // to end the loop
break;
case MESSAGE:
if( is_fd_valid(destination) )
{
tmp_ptr=buf;
while(*tmp_ptr==' ')
++tmp_ptr;
c=destination;
*(tmp_ptr+1)=i+'0';//(char)destination;
tmp_ptr=strchr(buf,'\n');
//str_len=strlen(buf);
write_to_socket(destination,buf,tmp_ptr-buf+1);
printf("\nGood show\n");
}
else
{
bzero(buf,sizeof(buf));
strcpy(buf,"Invalid user\n>>\r\n");
str_len=strlen(buf);
write_to_socket(i,buf,str_len);
}
j=1111; // to end the loop
break;
case HELP:
bzero(buf,sizeof(buf));
strcpy(buf,"\n\n\n********************************************************************************\n\n\n"
"\t\t\t~Type /SHOW/ to list all online users\n\n"
"\t~ To send a message to everyone in the room \n"
"\t\t\tjust type the message and press enter\n\n"
"\t\t~ Type /numeric-user/ to send a message to particular user only\n\n"
"\t\t\t\t ex: /6/ Hi number 6 how r u\n\n"
"\t\t\t~ Type /HELP/ to see server commands\n\n\n>>"
"********************************************************************************\n\n\n\n>>" );
str_len=strlen(buf);
write_to_socket(newfd,buf,str_len);
j=1111;
break;
case NEWLINE:
bzero(buf,sizeof(buf));
sprintf(buf,">>");
//str_len=strlen(buf);
write_to_socket(i,buf,strlen(buf));
j=1111;
break;
case NICK:
//printf("Got the nick\n");
//bzero(buf,sizeof(buf));
printf(buf);
tmp_ptr=buf;
tmp_ptr+=6;
for(tmp=0;tmp<fdmax;++tmp)
{
if(user[tmp].id==i)
break;
}
user[tmp].flag_nick=1;
strncpy(user[tmp].nick,tmp_ptr,10);
bzero(buf,sizeof(buf));
sprintf(buf,"%s Joined the room\r\n",user[tmp].nick);
str_len=strlen(buf);
write_to_socket(j,buf,str_len);
j=1111; // to end the loop
break;
default:
write_to_socket(j,buf,nbytes);
break;
}
}
}
}
}
}
}
}
}
return 0;
}
void write_to_socket(int target,char *buff_to_send,int len)
{
if( !write(target,buff_to_send,len) )
{
perror("Write");
exit(0);
}
}
int check_for_command(char *buffer,int *p)
{
char tmp[6];
strncpy(tmp,buffer,5);
while(*buffer==' ')
++buffer;
if(!strncmp(buffer,"/SHOW/",6) || !strncmp(buffer,"/show/",6) )
return SHOW;
else if(!strncmp(buffer,"/HELP/",6) || !strncmp(buffer,"/help/",6) )
return HELP;
else if(!strncmp(buffer,"/NICK/",6) || !strncmp(buffer,"/NICK/",6) )
return NICK;
else if((*buffer=='/') && (*(buffer+2)=='/'))
{
*p= *(buffer+1)-'0';
return MESSAGE;
}
else if( *buffer=='\r')
return NEWLINE;
else
return 0;
}
int is_fd_valid(int destination)
{
int i;
for(i=0;i<usercount;++i)
if( user[i].id==destination)
return 1;
return 0;
}
void type_writer(char *buf,int len, int fd)
{
int i=0;
for(i=0;i<len;++i)
{
write_to_socket(fd,buf+i,sizeof(char));
usleep(50000);
}
}