Клиент - серверное приложение на Си  
Автор Сообщение

0
Сообщение Клиент - серверное приложение на Си
Помогите плиз допилить код, вобщем нужно сделать чтобы сервер при получении сообщения отправлял его всем подключенным клиентам (исключая отправителя). Нужно сделать через массив или связанный список.


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define NLISTEN 1024
#define server_name (argv[0])

/*----------------------------------------------------------------------------*/

void error(int status, int err, char* fmt, ...)
{
va_list ap;
va_start(ap,fmt);
vfprintf(stderr,fmt,ap);
va_end(ap);
if(err)
fprintf(stderr, " error %d: %s\n",err,strerror(err));
if(status)
exit(status);
}

/*---------------------------------------------------------------------------*/

/* main function */
int main (int argc, char** argv)
{
/*Sockets*/
int srv_st = 0, clt_st = 0;
struct sockaddr_in clt_addr, srv_addr; /*client and server addr's */
socklen_t sockaddrsize = sizeof(struct sockaddr_in);

char *host = 0, *sport = 0;
fd_set master; /* master file descriptor list */
fd_set read_fds; /* temp fd list for select() */

int fdmax = 0; /* need for keep max fd */
int res = 0; /* for returns values */
int i = 0, j = 0; /* iterators */

char buf[32768]; /* buffer for received data */
bzero (buf, 32768); /*clear buf*/

struct servent *sp;
struct hostent *hp;
char *endptr;
short port; /* port number */

int op = 1; /* needed for sockopt */

/* parse command line */
if(argc != 2)
printf("usage: %s \n", argv[0]), exit(0);
else
host = 0, sport = argv[1];

/* clear fd lists */
FD_ZERO(&master);
FD_ZERO(&read_fds);

/* fill server address */
bzero ((void*)&srv_addr, sizeof(srv_addr)); /* fill zeroes */

srv_addr.sin_family = PF_INET;
srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

/* fill port */
port = strtol( sport, &endptr, 0);
if( *endptr == '\0' )
srv_addr.sin_port = htons(port);
else
{
error(1,0,"unknown service: %s\n",sport);
}

/* Create TCP based socket */
srv_st = socket(PF_INET, SOCK_STREAM, 0);
if( srv_st < 0 )
error(1, errno, "error socket");

/* set SO_REUSEADDR option */
res = setsockopt(srv_st, SOL_SOCKET, SO_REUSEADDR, (const char*)&op,sizeof(op));
if(res)
error(1, errno, "error setsockopt");

/* bind server socket to srv_addr */
res = bind(srv_st, (struct sockaddr*)&srv_addr, sockaddrsize);
int pt = 50000;
while (res)
{
if ( res < 0 )
{
error(0, errno, "error bind, try again with port %d",pt);
srv_addr.sin_port = htons(pt++);
if ( pt >= 55000 )
error(1,0,"error bind, no enough ports in range");
res = bind(srv_st, (struct sockaddr*)&srv_addr, sockaddrsize);
}
else
error(1, errno, "error bind");
}

/* create queue for clients requests */
res = listen(srv_st, NLISTEN);
if(res == -1)
error(1, errno, "listen");

/* add srv_st to master fd list */
FD_SET(srv_st, &master);

/* keep track of the biggest file descriptor */
fdmax = srv_st;

/* main loop */
for(;;)
{
read_fds = master; /* copy master list */

/* waiting new connection or data */
if (select( fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
{
error(1, errno, "select");
}

/* run through the existing connections looking for data to read */
for( i=0; i<=fdmax; i++)
{
if(FD_ISSET(i, &read_fds)) /* we have got new data */
{
if( i == srv_st )
{
/* wait new connection */
clt_st = accept(srv_st, (struct sockaddr*)&clt_addr, &sockaddrsize);
if( clt_st < 0)
error(0, errno,"error accept");
else
{
FD_SET(clt_st, &master); /* add new socket to master */
if( clt_st > fdmax )
fdmax = clt_st; /* keep max descriptor */
}
}
else
{
/* got new data */
res = read(i, buf, sizeof(buf));

if( res <= 0)
{
/* client closed connection */
if( res == 0 )
{
/* close socket and del i from master */
close(i);
FD_CLR(i, &master);
}
}
else
{
/* we have got a msg in buf from i client */
/* send message back */
printf ("recieved %d bytes\n",res);
res = write(i, buf, res);
if( res == -1 )
error(0,errno,"send");
printf ("sent %d bytes\n",res);
}
}
}
}
}
/* close srv_st socket */
close (srv_st);
return 0;
}



если есть готовый то вобще шикарно :D


01 фев 2012, 22:11
Профиль



<Адский Кипиш>


Сервер: Свежеватель Душ
Рейтинг поля боя: 956
2х2: 2013
3х3: 1821
5х5: 1947
0
Сообщение Клиент - серверное приложение на Си
Ты пришёл в нужное место, бро.


02 фев 2012, 04:06
Профиль ICQ

1
Сообщение Клиент - серверное приложение на Си
Код:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define NLISTEN 1024
#define server_name (argv[0])

/*----------------------------------------------------------------------------*/

void error(int status, int err, char* fmt, ...)
{
va_list ap;
va_start(ap,fmt);
vfprintf(stderr,fmt,ap);
va_end(ap);
if(err)
fprintf(stderr, " error %d: %s\n",err,strerror(err));
if(status)
exit(status);
}

/*---------------------------------------------------------------------------*/

/* main function */
int main (int argc, char** argv)
{
/*Sockets*/
int srv_st = 0, clt_st = 0;
struct sockaddr_in clt_addr, srv_addr; /*client and server addr's */
socklen_t sockaddrsize = sizeof(struct sockaddr_in);

char *host = 0, *sport = 0;
fd_set master; /* master file descriptor list */
fd_set read_fds; /* temp fd list for select() */

int fdmax = 0; /* need for keep max fd */
int res = 0; /* for returns values */
int i = 0, j = 0; /* iterators */

char buf[32768]; /* buffer for received data */
bzero (buf, 32768); /*clear buf*/

struct servent *sp;
struct hostent *hp;
char *endptr;
short port; /* port number */

int op = 1; /* needed for sockopt */

/* parse command line */
if(argc != 2)
printf("usage: %s \n", argv[0]), exit(0);
else
host = 0, sport = argv[1];

/* clear fd lists */
FD_ZERO(&master);
FD_ZERO(&read_fds);

/* fill server address */
bzero ((void*)&srv_addr, sizeof(srv_addr)); /* fill zeroes */

srv_addr.sin_family = PF_INET;
srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

/* fill port */
port = strtol( sport, &endptr, 0);
if( *endptr == '\0' )
srv_addr.sin_port = htons(port);
else
{
error(1,0,"unknown service: %s\n",sport);
}

/* Create TCP based socket */
srv_st = socket(PF_INET, SOCK_STREAM, 0);
if( srv_st < 0 )
error(1, errno, "error socket");

/* set SO_REUSEADDR option */
res = setsockopt(srv_st, SOL_SOCKET, SO_REUSEADDR, (const char*)&op,sizeof(op));
if(res)
error(1, errno, "error setsockopt");

/* bind server socket to srv_addr */
res = bind(srv_st, (struct sockaddr*)&srv_addr, sockaddrsize);
int pt = 50000;
while (res)
{
if ( res < 0 )
{
error(0, errno, "error bind, try again with port %d",pt);
srv_addr.sin_port = htons(pt++);
if ( pt >= 55000 )
error(1,0,"error bind, no enough ports in range");
res = bind(srv_st, (struct sockaddr*)&srv_addr, sockaddrsize);
}
else
error(1, errno, "error bind");
}

/* create queue for clients requests */
res = listen(srv_st, NLISTEN);
if(res == -1)
error(1, errno, "listen");

/* add srv_st to master fd list */
FD_SET(srv_st, &master);

/* keep track of the biggest file descriptor */
fdmax = srv_st;

/* main loop */
for(;;)
{
read_fds = master; /* copy master list */

/* waiting new connection or data */
if (select( fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
{
error(1, errno, "select");
}

/* run through the existing connections looking for data to read */
for( i=0; i<=fdmax; i++)
{
if(FD_ISSET(i, &read_fds)) /* we have got new data */
{
if( i == srv_st )
{
/* wait new connection */
clt_st = accept(srv_st, (struct sockaddr*)&clt_addr, &sockaddrsize);
if( clt_st < 0)
error(0, errno,"error accept");
else
{
FD_SET(clt_st, &master); /* add new socket to master */
if( clt_st > fdmax )
fdmax = clt_st; /* keep max descriptor */
}
}
else
{
/* got new data */
res = read(i, buf, sizeof(buf));

if( res <= 0)
{
/* client closed connection */
if( res == 0 )
{
/* close socket and del i from master */
close(i);
FD_CLR(i, &master);
}
}
else
{
/* we have got a msg in buf from i client */
/* send message back */
printf ("recieved %d bytes\n",res);
for(j = 0; j <=fdmax; j++)
{
   if(FD_ISSET(j, &master))
   {
      if((j != srv_st) && (j != i))
      {
         res = write(j, buf, res);
         if( res == -1 )
         error(0,errno,"send");
         printf ("sent %d bytes to fd=%d\n",res,j);
      }
   }
}
}
}
}
}
}
/* close srv_st socket */
close (srv_st);
return 0;
}
и никаких дополнительных массивов и списков не нужно, в master хранятся все открытые дескрипторы... а так тут много чего нету, обработки всяких ошибок и тп (в частности если клиент отвалится по таймауту)... и вообще я бы смотрел в сторону libevent/libev и тп если нужен такой функционал...


02 фев 2012, 04:59
Профиль ICQ

0
Сообщение Клиент - серверное приложение на Си
Фу, Си :(


02 фев 2012, 09:05
Профиль

0
Сообщение Клиент - серверное приложение на Си
Ph34rd писал(а):

Код:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define NLISTEN 1024
#define server_name (argv[0])

/*----------------------------------------------------------------------------*/

void error(int status, int err, char* fmt, ...)
{
va_list ap;
va_start(ap,fmt);
vfprintf(stderr,fmt,ap);
va_end(ap);
if(err)
fprintf(stderr, " error %d: %s\n",err,strerror(err));
if(status)
exit(status);
}

/*---------------------------------------------------------------------------*/

/* main function */
int main (int argc, char** argv)
{
/*Sockets*/
int srv_st = 0, clt_st = 0;
struct sockaddr_in clt_addr, srv_addr; /*client and server addr's */
socklen_t sockaddrsize = sizeof(struct sockaddr_in);

char *host = 0, *sport = 0;
fd_set master; /* master file descriptor list */
fd_set read_fds; /* temp fd list for select() */

int fdmax = 0; /* need for keep max fd */
int res = 0; /* for returns values */
int i = 0, j = 0; /* iterators */

char buf[32768]; /* buffer for received data */
bzero (buf, 32768); /*clear buf*/

struct servent *sp;
struct hostent *hp;
char *endptr;
short port; /* port number */

int op = 1; /* needed for sockopt */

/* parse command line */
if(argc != 2)
printf("usage: %s \n", argv[0]), exit(0);
else
host = 0, sport = argv[1];

/* clear fd lists */
FD_ZERO(&master);
FD_ZERO(&read_fds);

/* fill server address */
bzero ((void*)&srv_addr, sizeof(srv_addr)); /* fill zeroes */

srv_addr.sin_family = PF_INET;
srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

/* fill port */
port = strtol( sport, &endptr, 0);
if( *endptr == '\0' )
srv_addr.sin_port = htons(port);
else
{
error(1,0,"unknown service: %s\n",sport);
}

/* Create TCP based socket */
srv_st = socket(PF_INET, SOCK_STREAM, 0);
if( srv_st < 0 )
error(1, errno, "error socket");

/* set SO_REUSEADDR option */
res = setsockopt(srv_st, SOL_SOCKET, SO_REUSEADDR, (const char*)&op,sizeof(op));
if(res)
error(1, errno, "error setsockopt");

/* bind server socket to srv_addr */
res = bind(srv_st, (struct sockaddr*)&srv_addr, sockaddrsize);
int pt = 50000;
while (res)
{
if ( res < 0 )
{
error(0, errno, "error bind, try again with port %d",pt);
srv_addr.sin_port = htons(pt++);
if ( pt >= 55000 )
error(1,0,"error bind, no enough ports in range");
res = bind(srv_st, (struct sockaddr*)&srv_addr, sockaddrsize);
}
else
error(1, errno, "error bind");
}

/* create queue for clients requests */
res = listen(srv_st, NLISTEN);
if(res == -1)
error(1, errno, "listen");

/* add srv_st to master fd list */
FD_SET(srv_st, &master);

/* keep track of the biggest file descriptor */
fdmax = srv_st;

/* main loop */
for(;;)
{
read_fds = master; /* copy master list */

/* waiting new connection or data */
if (select( fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
{
error(1, errno, "select");
}

/* run through the existing connections looking for data to read */
for( i=0; i<=fdmax; i++)
{
if(FD_ISSET(i, &read_fds)) /* we have got new data */
{
if( i == srv_st )
{
/* wait new connection */
clt_st = accept(srv_st, (struct sockaddr*)&clt_addr, &sockaddrsize);
if( clt_st < 0)
error(0, errno,"error accept");
else
{
FD_SET(clt_st, &master); /* add new socket to master */
if( clt_st > fdmax )
fdmax = clt_st; /* keep max descriptor */
}
}
else
{
/* got new data */
res = read(i, buf, sizeof(buf));

if( res <= 0)
{
/* client closed connection */
if( res == 0 )
{
/* close socket and del i from master */
close(i);
FD_CLR(i, &master);
}
}
else
{
/* we have got a msg in buf from i client */
/* send message back */
printf ("recieved %d bytes\n",res);
for(j = 0; j <=fdmax; j++)
{
   if(FD_ISSET(j, &master))
   {
      if((j != srv_st) && (j != i))
      {
         res = write(j, buf, res);
         if( res == -1 )
         error(0,errno,"send");
         printf ("sent %d bytes to fd=%d\n",res,j);
      }
   }
}
}
}
}
}
}
/* close srv_st socket */
close (srv_st);
return 0;
}
и никаких дополнительных массивов и списков не нужно, в master хранятся все открытые дескрипторы... а так тут много чего нету, обработки всяких ошибок и тп (в частности если клиент отвалится по таймауту)... и вообще я бы смотрел в сторону libevent/libev и тп если нужен такой функционал...


благодарствую :drink


03 фев 2012, 16:03
Профиль
Начать новую тему Ответить на тему


Перейти:  

На сайте использованы материалы, принадлежащие Blizzard Entertainment. Копирование материалов возможно только c разрешения портала. В противном случае это будет называться уже другим словом.
Рейтинг@Mail.ru