#include #include #include #include #include #include #include #include #include #include #include #include void PrintAddr(const struct sockaddr_in &addr, const char *text); #define PORT 5555 #define BUFLEN 512 char buf[BUFLEN]; #define MAX_CLIENTS 8 struct ClientsInfo { // структура для регистрации обратившихся клиентов int num_clients; struct sockaddr_in info[MAX_CLIENTS]; ClientsInfo() { num_clients = 0;} }; void ProcessRequest (int sock, ClientsInfo &clients); int main(void) { int sock; int nbytes, i, err; unsigned int size; struct sockaddr_in addr_this; // для входящих запросов struct hostent *hostinfo; hostinfo = gethostbyname("127.0.0.1"); if ( hostinfo==NULL ) { fprintf (stderr, "Unknown host\n"); exit (EXIT_FAILURE); } addr_this.sin_family = AF_INET; addr_this.sin_addr.s_addr = INADDR_ANY; addr_this.sin_port = htons(PORT); // Создаем TCP сокет. sock = socket(PF_INET,SOCK_DGRAM,0); if ( sock<0 ) { perror ("Client: socket was not created"); exit (EXIT_FAILURE); } int opt = 1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&opt,sizeof(opt)); // Привязываем сокет к сетевому интерфейсу err = bind(sock, (struct sockaddr*)&addr_this, sizeof(addr_this)); if ( err<0 ) { perror ("Client: cannot bind socket"); exit (EXIT_FAILURE); } // работа с клиентами ClientsInfo clients; // снимаем блокировку чтения на сокете fcntl(sock, F_SETFL, O_NONBLOCK); // обрабатываем входящие запросы и формируем исходящие сообщения ProcessRequest (sock, clients); close(sock); return 0; } void PrintAddr(const struct sockaddr_in &addr, const char *text) { if (text) printf("%s", text); int f = addr.sin_family; int p = addr.sin_port; printf("type %d\n", f); printf("port %d\n", ntohs(p)); printf("ip addr %s\n", inet_ntoa(addr.sin_addr)); } void ProcessRequest (int sock, ClientsInfo &clients) { int base_delay = 1000; // задержка в выполнении цикла подсчета времени int base_period = 5000; // базовый интервал рассылки сообщений о времени struct timeval tv; struct sockaddr_in addr_from; // откуда пришло unsigned int size; int nbytes; int r, period = base_period; const char *msg; // основной цикл обработки запросов и рассылки for (int i=0; true; i++) { // проверка запроса от клиента - // если пришло сообщение - регистрируем нового клиента size = sizeof(struct sockaddr_in); nbytes = recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr*)&addr_from, &size); if( nbytes>0 ) { printf("get %d bytes\n", nbytes); PrintAddr(addr_from, "get message from\n"); if (clients.num_clients >= MAX_CLIENTS) { printf("cannot register new client\n"); } else { // регистрация клиента clients.info[clients.num_clients++] = addr_from; } } // проверка момента рассылки сообщений // выполнилось некоторое количество шагов цикла - пора рассылать сообщение if (i > period) { r = rand(); gettimeofday(&tv, 0); // текущее время msg = ctime(&(tv.tv_sec)); sprintf(buf, "%10d %s", r, msg); printf( "%s\n", buf); // рассылка по всем зарегистрированным клиентам for (int j=0; j